Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ decb4714

History | View | Annotate | Download (97 kB)

1
/*
2
 *  PowerPC emulation helpers for qemu.
3
 *
4
 *  Copyright (c) 2003-2007 Jocelyn Mayer
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include <stdarg.h>
20
#include <stdlib.h>
21
#include <stdio.h>
22
#include <string.h>
23
#include <inttypes.h>
24
#include <signal.h>
25

    
26
#include "cpu.h"
27
#include "exec-all.h"
28
#include "helper_regs.h"
29
#include "qemu-common.h"
30
#include "kvm.h"
31

    
32
//#define DEBUG_MMU
33
//#define DEBUG_BATS
34
//#define DEBUG_SLB
35
//#define DEBUG_SOFTWARE_TLB
36
//#define DUMP_PAGE_TABLES
37
//#define DEBUG_EXCEPTIONS
38
//#define FLUSH_ALL_TLBS
39

    
40
#ifdef DEBUG_MMU
41
#  define LOG_MMU(...) qemu_log(__VA_ARGS__)
42
#  define LOG_MMU_STATE(env) log_cpu_state((env), 0)
43
#else
44
#  define LOG_MMU(...) do { } while (0)
45
#  define LOG_MMU_STATE(...) do { } while (0)
46
#endif
47

    
48

    
49
#ifdef DEBUG_SOFTWARE_TLB
50
#  define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
51
#else
52
#  define LOG_SWTLB(...) do { } while (0)
53
#endif
54

    
55
#ifdef DEBUG_BATS
56
#  define LOG_BATS(...) qemu_log(__VA_ARGS__)
57
#else
58
#  define LOG_BATS(...) do { } while (0)
59
#endif
60

    
61
#ifdef DEBUG_SLB
62
#  define LOG_SLB(...) qemu_log(__VA_ARGS__)
63
#else
64
#  define LOG_SLB(...) do { } while (0)
65
#endif
66

    
67
#ifdef DEBUG_EXCEPTIONS
68
#  define LOG_EXCP(...) qemu_log(__VA_ARGS__)
69
#else
70
#  define LOG_EXCP(...) do { } while (0)
71
#endif
72

    
73
/*****************************************************************************/
74
/* PowerPC Hypercall emulation */
75

    
76
void (*cpu_ppc_hypercall)(CPUState *);
77

    
78
/*****************************************************************************/
79
/* PowerPC MMU emulation */
80

    
81
#if defined(CONFIG_USER_ONLY)
82
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
83
                              int mmu_idx, int is_softmmu)
84
{
85
    int exception, error_code;
86

    
87
    if (rw == 2) {
88
        exception = POWERPC_EXCP_ISI;
89
        error_code = 0x40000000;
90
    } else {
91
        exception = POWERPC_EXCP_DSI;
92
        error_code = 0x40000000;
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;
100

    
101
    return 1;
102
}
103

    
104
#else
105
/* Common routines used by software and hardware TLBs emulation */
106
static inline int pte_is_valid(target_ulong pte0)
107
{
108
    return pte0 & 0x80000000 ? 1 : 0;
109
}
110

    
111
static inline void pte_invalidate(target_ulong *pte0)
112
{
113
    *pte0 &= ~0x80000000;
114
}
115

    
116
#if defined(TARGET_PPC64)
117
static inline int pte64_is_valid(target_ulong pte0)
118
{
119
    return pte0 & 0x0000000000000001ULL ? 1 : 0;
120
}
121

    
122
static inline void pte64_invalidate(target_ulong *pte0)
123
{
124
    *pte0 &= ~0x0000000000000001ULL;
125
}
126
#endif
127

    
128
#define PTE_PTEM_MASK 0x7FFFFFBF
129
#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
130
#if defined(TARGET_PPC64)
131
#define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
132
#define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
133
#endif
134

    
135
static inline int pp_check(int key, int pp, int nx)
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

    
175
static inline int check_prot(int prot, int rw, int access_type)
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

    
199
static inline int _pte_check(mmu_ctx_t *ctx, int is_64b, target_ulong pte0,
200
                             target_ulong pte1, int h, int rw, int type)
201
{
202
    target_ulong ptem, mmask;
203
    int access, ret, pteh, ptev, pp;
204

    
205
    ret = -1;
206
    /* Check validity and table match */
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) {
218
        /* Check vsid & api */
219
#if defined(TARGET_PPC64)
220
        if (is_64b) {
221
            ptem = pte0 & PTE64_PTEM_MASK;
222
            mmask = PTE64_CHECK_MASK;
223
            pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
224
            ctx->nx  = (pte1 >> 2) & 1; /* No execute bit */
225
            ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
226
        } else
227
#endif
228
        {
229
            ptem = pte0 & PTE_PTEM_MASK;
230
            mmask = PTE_CHECK_MASK;
231
            pp = pte1 & 0x00000003;
232
        }
233
        if (ptem == ctx->ptem) {
234
            if (ctx->raddr != (target_phys_addr_t)-1ULL) {
235
                /* all matches should have equal RPN, WIMG & PP */
236
                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
237
                    qemu_log("Bad RPN/WIMG/PP\n");
238
                    return -3;
239
                }
240
            }
241
            /* Compute access rights */
242
            access = pp_check(ctx->key, pp, ctx->nx);
243
            /* Keep the matching PTE informations */
244
            ctx->raddr = pte1;
245
            ctx->prot = access;
246
            ret = check_prot(ctx->prot, rw, type);
247
            if (ret == 0) {
248
                /* Access granted */
249
                LOG_MMU("PTE access granted !\n");
250
            } else {
251
                /* Access right violation */
252
                LOG_MMU("PTE access rejected\n");
253
            }
254
        }
255
    }
256

    
257
    return ret;
258
}
259

    
260
static inline int pte32_check(mmu_ctx_t *ctx, target_ulong pte0,
261
                              target_ulong pte1, int h, int rw, int type)
262
{
263
    return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
264
}
265

    
266
#if defined(TARGET_PPC64)
267
static inline int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
268
                              target_ulong pte1, int h, int rw, int type)
269
{
270
    return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
271
}
272
#endif
273

    
274
static inline int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
275
                                   int ret, int rw)
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 */
300
static inline int ppc6xx_tlb_getnum(CPUState *env, target_ulong eaddr, int way,
301
                                    int is_code)
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

    
316
static inline void ppc6xx_tlb_invalidate_all(CPUState *env)
317
{
318
    ppc6xx_tlb_t *tlb;
319
    int nr, max;
320

    
321
    //LOG_SWTLB("Invalidate all TLBs\n");
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++) {
327
        tlb = &env->tlb[nr].tlb6;
328
        pte_invalidate(&tlb->pte0);
329
    }
330
    tlb_flush(env, 1);
331
}
332

    
333
static inline void __ppc6xx_tlb_invalidate_virt(CPUState *env,
334
                                                target_ulong eaddr,
335
                                                int is_code, int match_epn)
336
{
337
#if !defined(FLUSH_ALL_TLBS)
338
    ppc6xx_tlb_t *tlb;
339
    int way, nr;
340

    
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);
344
        tlb = &env->tlb[nr].tlb6;
345
        if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
346
            LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
347
                      env->nb_tlb, eaddr);
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

    
358
static inline void ppc6xx_tlb_invalidate_virt(CPUState *env,
359
                                              target_ulong eaddr, int is_code)
360
{
361
    __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
362
}
363

    
364
void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
365
                       target_ulong pte0, target_ulong pte1)
366
{
367
    ppc6xx_tlb_t *tlb;
368
    int nr;
369

    
370
    nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
371
    tlb = &env->tlb[nr].tlb6;
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);
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;
379
    /* Store last way for LRU mechanism */
380
    env->last_way = way;
381
}
382

    
383
static inline int ppc6xx_tlb_check(CPUState *env, mmu_ctx_t *ctx,
384
                                   target_ulong eaddr, int rw, int access_type)
385
{
386
    ppc6xx_tlb_t *tlb;
387
    int nr, best, way;
388
    int ret;
389

    
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);
395
        tlb = &env->tlb[nr].tlb6;
396
        /* This test "emulates" the PTE index match for hardware TLBs */
397
        if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
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);
402
            continue;
403
        }
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');
409
        switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
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:
435
        LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
436
                  ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
437
        /* Update page flags */
438
        pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
439
    }
440

    
441
    return ret;
442
}
443

    
444
/* Perform BAT hit & translation */
445
static inline void bat_size_prot(CPUState *env, target_ulong *blp, int *validp,
446
                                 int *protp, target_ulong *BATu,
447
                                 target_ulong *BATl)
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

    
470
static inline void bat_601_size_prot(CPUState *env, target_ulong *blp,
471
                                     int *validp, int *protp,
472
                                     target_ulong *BATu, target_ulong *BATl)
473
{
474
    target_ulong bl;
475
    int key, pp, valid, prot;
476

    
477
    bl = (*BATl & 0x0000003F) << 17;
478
    LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
479
             (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
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

    
495
static inline int get_bat(CPUState *env, mmu_ctx_t *ctx, target_ulong virtual,
496
                          int rw, int type)
497
{
498
    target_ulong *BATlt, *BATut, *BATu, *BATl;
499
    target_ulong BEPIl, BEPIu, bl;
500
    int i, valid, prot;
501
    int ret = -1;
502

    
503
    LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
504
             type == ACCESS_CODE ? 'I' : 'D', virtual);
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
    }
515
    for (i = 0; i < env->nb_BATs; i++) {
516
        BATu = &BATut[i];
517
        BATl = &BATlt[i];
518
        BEPIu = *BATu & 0xF0000000;
519
        BEPIl = *BATu & 0x0FFE0000;
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
        }
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);
528
        if ((virtual & 0xF0000000) == BEPIu &&
529
            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
530
            /* BAT matches */
531
            if (valid != 0) {
532
                /* Get physical address */
533
                ctx->raddr = (*BATl & 0xF0000000) |
534
                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
535
                    (virtual & 0x0001F000);
536
                /* Compute access rights */
537
                ctx->prot = prot;
538
                ret = check_prot(ctx->prot, rw, type);
539
                if (ret == 0)
540
                    LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
541
                             i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
542
                             ctx->prot & PAGE_WRITE ? 'W' : '-');
543
                break;
544
            }
545
        }
546
    }
547
    if (ret < 0) {
548
#if defined(DEBUG_BATS)
549
        if (qemu_log_enabled()) {
550
            LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
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;
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",
560
                         __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
561
                         *BATu, *BATl, BEPIu, BEPIl, bl);
562
            }
563
        }
564
#endif
565
    }
566
    /* No hit */
567
    return ret;
568
}
569

    
570
static 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

    
577
/* PTE table lookup */
578
static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
579
                            int rw, int type, int target_page_bits)
580
{
581
    target_phys_addr_t pteg_off;
582
    target_ulong pte0, pte1;
583
    int i, good = -1;
584
    int ret, r;
585

    
586
    ret = -1; /* No entry found */
587
    pteg_off = get_pteg_offset(env, ctx->hash[h],
588
                               is_64b ? HASH_PTE_SIZE_64 : HASH_PTE_SIZE_32);
589
    for (i = 0; i < 8; i++) {
590
#if defined(TARGET_PPC64)
591
        if (is_64b) {
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
            }
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

    
606
            r = pte64_check(ctx, pte0, pte1, h, rw, type);
607
            LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
608
                    TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
609
                    pteg_off + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
610
                    (int)((pte0 >> 1) & 1), ctx->ptem);
611
        } else
612
#endif
613
        {
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
            }
621
            r = pte32_check(ctx, pte0, pte1, h, rw, type);
622
            LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
623
                    TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
624
                    pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
625
                    (int)((pte0 >> 6) & 1), ctx->ptem);
626
        }
627
        switch (r) {
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;
649
        }
650
    }
651
    if (good != -1) {
652
    done:
653
        LOG_MMU("found PTE at addr " TARGET_FMT_lx " prot=%01x ret=%d\n",
654
                ctx->raddr, ctx->prot, ret);
655
        /* Update page flags */
656
        pte1 = ctx->raddr;
657
        if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
658
#if defined(TARGET_PPC64)
659
            if (is_64b) {
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
                }
667
            } else
668
#endif
669
            {
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
                }
677
            }
678
        }
679
    }
680

    
681
    return ret;
682
}
683

    
684
static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
685
                           int type, int target_page_bits)
686
{
687
#if defined(TARGET_PPC64)
688
    if (env->mmu_model & POWERPC_MMU_64)
689
        return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
690
#endif
691

    
692
    return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
693
}
694

    
695
#if defined(TARGET_PPC64)
696
static inline ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
697
{
698
    uint64_t esid_256M, esid_1T;
699
    int n;
700

    
701
    LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
702

    
703
    esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
704
    esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V;
705

    
706
    for (n = 0; n < env->slb_nr; n++) {
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);
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))) {
718
            return slb;
719
        }
720
    }
721

    
722
    return NULL;
723
}
724

    
725
void ppc_slb_invalidate_all (CPUPPCState *env)
726
{
727
    int n, do_invalidate;
728

    
729
    do_invalidate = 0;
730
    /* XXX: Warning: slbia never invalidates the first segment */
731
    for (n = 1; n < env->slb_nr; n++) {
732
        ppc_slb_t *slb = &env->slb[n];
733

    
734
        if (slb->esid & SLB_ESID_V) {
735
            slb->esid &= ~SLB_ESID_V;
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
        }
742
    }
743
    if (do_invalidate)
744
        tlb_flush(env, 1);
745
}
746

    
747
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
748
{
749
    ppc_slb_t *slb;
750

    
751
    slb = slb_lookup(env, T0);
752
    if (!slb) {
753
        return;
754
    }
755

    
756
    if (slb->esid & SLB_ESID_V) {
757
        slb->esid &= ~SLB_ESID_V;
758

    
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
    }
765
}
766

    
767
int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
768
{
769
    int slot = rb & 0xfff;
770
    ppc_slb_t *slb = &env->slb[slot];
771

    
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 */
780
    }
781

    
782
    /* Mask out the slot number as we store the entry */
783
    slb->esid = rb & (SLB_ESID_ESID | SLB_ESID_V);
784
    slb->vsid = rs;
785

    
786
    LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
787
            " %016" PRIx64 "\n", __func__, slot, rb, rs,
788
            slb->esid, slb->vsid);
789

    
790
    return 0;
791
}
792

    
793
int 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

    
806
int 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
}
818
#endif /* defined(TARGET_PPC64) */
819

    
820
/* Perform segment based translation */
821
static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
822
                              target_ulong eaddr, int rw, int type)
823
{
824
    target_phys_addr_t hash;
825
    target_ulong vsid;
826
    int ds, pr, target_page_bits;
827
    int ret, ret2;
828

    
829
    pr = msr_pr;
830
    ctx->eaddr = eaddr;
831
#if defined(TARGET_PPC64)
832
    if (env->mmu_model & POWERPC_MMU_64) {
833
        ppc_slb_t *slb;
834
        target_ulong pageaddr;
835
        int segment_bits;
836

    
837
        LOG_MMU("Check SLBs\n");
838
        slb = slb_lookup(env, eaddr);
839
        if (!slb) {
840
            return -5;
841
        }
842

    
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

    
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));
855
        ds = 0;
856
        ctx->nx = !!(slb->vsid & SLB_VSID_N);
857

    
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
        }
865
        /* Only 5 bits of the page index are used in the AVPN */
866
        ctx->ptem = (slb->vsid & SLB_VSID_PTEM) |
867
            ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
868
    } else
869
#endif /* defined(TARGET_PPC64) */
870
    {
871
        target_ulong sr, pgidx;
872

    
873
        sr = env->sr[eaddr >> 28];
874
        ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
875
                    ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
876
        ds = sr & 0x80000000 ? 1 : 0;
877
        ctx->nx = sr & 0x10000000 ? 1 : 0;
878
        vsid = sr & 0x00FFFFFF;
879
        target_page_bits = TARGET_PAGE_BITS;
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);
885
        pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
886
        hash = vsid ^ pgidx;
887
        ctx->ptem = (vsid << 7) | (pgidx >> 10);
888
    }
889
    LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
890
            ctx->key, ds, ctx->nx, vsid);
891
    ret = -1;
892
    if (!ds) {
893
        /* Check if instruction fetch is allowed, if needed */
894
        if (type != ACCESS_CODE || ctx->nx == 0) {
895
            /* Page address translation */
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);
899
            ctx->hash[0] = hash;
900
            ctx->hash[1] = ~hash;
901

    
902
            /* Initialize real address with an invalid value */
903
            ctx->raddr = (target_phys_addr_t)-1ULL;
904
            if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
905
                         env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
906
                /* Software TLB search */
907
                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
908
            } else {
909
                LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
910
                        " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
911
                        " hash=" TARGET_FMT_plx "\n",
912
                        env->htab_base, env->htab_mask, vsid, ctx->ptem,
913
                        ctx->hash[0]);
914
                /* Primary table lookup */
915
                ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
916
                if (ret < 0) {
917
                    /* Secondary table lookup */
918
                    if (eaddr != 0xEFFFFFFF)
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 "\n", env->htab_base,
922
                                env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
923
                    ret2 = find_pte(env, ctx, 1, rw, type,
924
                                    target_page_bits);
925
                    if (ret2 != -1)
926
                        ret = ret2;
927
                }
928
            }
929
#if defined (DUMP_PAGE_TABLES)
930
            if (qemu_log_enabled()) {
931
                target_phys_addr_t curaddr;
932
                uint32_t a0, a1, a2, a3;
933
                qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
934
                         "\n", sdr, mask + 0x80);
935
                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
936
                     curaddr += 16) {
937
                    a0 = ldl_phys(curaddr);
938
                    a1 = ldl_phys(curaddr + 4);
939
                    a2 = ldl_phys(curaddr + 8);
940
                    a3 = ldl_phys(curaddr + 12);
941
                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
942
                        qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
943
                                 curaddr, a0, a1, a2, a3);
944
                    }
945
                }
946
            }
947
#endif
948
        } else {
949
            LOG_MMU("No access allowed\n");
950
            ret = -3;
951
        }
952
    } else {
953
        LOG_MMU("direct store...\n");
954
        /* Direct-store segment : absolutely *BUGGY* for now */
955
        switch (type) {
956
        case ACCESS_INT:
957
            /* Integer load/store : only access allowed */
958
            break;
959
        case ACCESS_CODE:
960
            /* No code fetch is allowed in direct-store areas */
961
            return -4;
962
        case ACCESS_FLOAT:
963
            /* Floating point load/store */
964
            return -4;
965
        case ACCESS_RES:
966
            /* lwarx, ldarx or srwcx. */
967
            return -4;
968
        case ACCESS_CACHE:
969
            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
970
            /* Should make the instruction do no-op.
971
             * As it already do no-op, it's quite easy :-)
972
             */
973
            ctx->raddr = eaddr;
974
            return 0;
975
        case ACCESS_EXT:
976
            /* eciwx or ecowx */
977
            return -4;
978
        default:
979
            qemu_log("ERROR: instruction should not need "
980
                        "address translation\n");
981
            return -4;
982
        }
983
        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
984
            ctx->raddr = eaddr;
985
            ret = 2;
986
        } else {
987
            ret = -2;
988
        }
989
    }
990

    
991
    return ret;
992
}
993

    
994
/* Generic TLB check function for embedded PowerPC implementations */
995
int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
996
                     target_phys_addr_t *raddrp,
997
                     target_ulong address, uint32_t pid, int ext,
998
                     int i)
999
{
1000
    target_ulong mask;
1001

    
1002
    /* Check valid flag */
1003
    if (!(tlb->prot & PAGE_VALID)) {
1004
        return -1;
1005
    }
1006
    mask = ~(tlb->size - 1);
1007
    LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
1008
              " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
1009
              mask, (uint32_t)tlb->PID, tlb->prot);
1010
    /* Check PID */
1011
    if (tlb->PID != 0 && tlb->PID != pid)
1012
        return -1;
1013
    /* Check effective address */
1014
    if ((address & mask) != tlb->EPN)
1015
        return -1;
1016
    *raddrp = (tlb->RPN & mask) | (address & ~mask);
1017
#if (TARGET_PHYS_ADDR_BITS >= 36)
1018
    if (ext) {
1019
        /* Extend the physical address to 36 bits */
1020
        *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1021
    }
1022
#endif
1023

    
1024
    return 0;
1025
}
1026

    
1027
/* Generic TLB search function for PowerPC embedded implementations */
1028
int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1029
{
1030
    ppcemb_tlb_t *tlb;
1031
    target_phys_addr_t raddr;
1032
    int i, ret;
1033

    
1034
    /* Default return value is no match */
1035
    ret = -1;
1036
    for (i = 0; i < env->nb_tlb; i++) {
1037
        tlb = &env->tlb[i].tlbe;
1038
        if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1039
            ret = i;
1040
            break;
1041
        }
1042
    }
1043

    
1044
    return ret;
1045
}
1046

    
1047
/* Helpers specific to PowerPC 40x implementations */
1048
static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
1049
{
1050
    ppcemb_tlb_t *tlb;
1051
    int i;
1052

    
1053
    for (i = 0; i < env->nb_tlb; i++) {
1054
        tlb = &env->tlb[i].tlbe;
1055
        tlb->prot &= ~PAGE_VALID;
1056
    }
1057
    tlb_flush(env, 1);
1058
}
1059

    
1060
static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
1061
                                              target_ulong eaddr, uint32_t pid)
1062
{
1063
#if !defined(FLUSH_ALL_TLBS)
1064
    ppcemb_tlb_t *tlb;
1065
    target_phys_addr_t raddr;
1066
    target_ulong page, end;
1067
    int i;
1068

    
1069
    for (i = 0; i < env->nb_tlb; i++) {
1070
        tlb = &env->tlb[i].tlbe;
1071
        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1072
            end = tlb->EPN + tlb->size;
1073
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1074
                tlb_flush_page(env, page);
1075
            tlb->prot &= ~PAGE_VALID;
1076
            break;
1077
        }
1078
    }
1079
#else
1080
    ppc4xx_tlb_invalidate_all(env);
1081
#endif
1082
}
1083

    
1084
static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1085
                                 target_ulong address, int rw, int access_type)
1086
{
1087
    ppcemb_tlb_t *tlb;
1088
    target_phys_addr_t raddr;
1089
    int i, ret, zsel, zpr, pr;
1090

    
1091
    ret = -1;
1092
    raddr = (target_phys_addr_t)-1ULL;
1093
    pr = msr_pr;
1094
    for (i = 0; i < env->nb_tlb; i++) {
1095
        tlb = &env->tlb[i].tlbe;
1096
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1097
                             env->spr[SPR_40x_PID], 0, i) < 0)
1098
            continue;
1099
        zsel = (tlb->attr >> 4) & 0xF;
1100
        zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
1101
        LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1102
                    __func__, i, zsel, zpr, rw, tlb->attr);
1103
        /* Check execute enable bit */
1104
        switch (zpr) {
1105
        case 0x2:
1106
            if (pr != 0)
1107
                goto check_perms;
1108
            /* No break here */
1109
        case 0x3:
1110
            /* All accesses granted */
1111
            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1112
            ret = 0;
1113
            break;
1114
        case 0x0:
1115
            if (pr != 0) {
1116
                /* Raise Zone protection fault.  */
1117
                env->spr[SPR_40x_ESR] = 1 << 22;
1118
                ctx->prot = 0;
1119
                ret = -2;
1120
                break;
1121
            }
1122
            /* No break here */
1123
        case 0x1:
1124
        check_perms:
1125
            /* Check from TLB entry */
1126
            ctx->prot = tlb->prot;
1127
            ret = check_prot(ctx->prot, rw, access_type);
1128
            if (ret == -2)
1129
                env->spr[SPR_40x_ESR] = 0;
1130
            break;
1131
        }
1132
        if (ret >= 0) {
1133
            ctx->raddr = raddr;
1134
            LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1135
                      " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1136
                      ret);
1137
            return 0;
1138
        }
1139
    }
1140
    LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1141
              " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1142

    
1143
    return ret;
1144
}
1145

    
1146
void store_40x_sler (CPUPPCState *env, uint32_t val)
1147
{
1148
    /* XXX: TO BE FIXED */
1149
    if (val != 0x00000000) {
1150
        cpu_abort(env, "Little-endian regions are not supported by now\n");
1151
    }
1152
    env->spr[SPR_405_SLER] = val;
1153
}
1154

    
1155
static inline int mmubooke_check_tlb (CPUState *env, ppcemb_tlb_t *tlb,
1156
                                      target_phys_addr_t *raddr, int *prot,
1157
                                      target_ulong address, int rw,
1158
                                      int access_type, int i)
1159
{
1160
    int ret, _prot;
1161

    
1162
    if (ppcemb_tlb_check(env, tlb, raddr, address,
1163
                         env->spr[SPR_BOOKE_PID],
1164
                         !env->nb_pids, i) >= 0) {
1165
        goto found_tlb;
1166
    }
1167

    
1168
    if (env->spr[SPR_BOOKE_PID1] &&
1169
        ppcemb_tlb_check(env, tlb, raddr, address,
1170
                         env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
1171
        goto found_tlb;
1172
    }
1173

    
1174
    if (env->spr[SPR_BOOKE_PID2] &&
1175
        ppcemb_tlb_check(env, tlb, raddr, address,
1176
                         env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
1177
        goto found_tlb;
1178
    }
1179

    
1180
    LOG_SWTLB("%s: TLB entry not found\n", __func__);
1181
    return -1;
1182

    
1183
found_tlb:
1184

    
1185
    if (msr_pr != 0) {
1186
        _prot = tlb->prot & 0xF;
1187
    } else {
1188
        _prot = (tlb->prot >> 4) & 0xF;
1189
    }
1190

    
1191
    /* Check the address space */
1192
    if (access_type == ACCESS_CODE) {
1193
        if (msr_ir != (tlb->attr & 1)) {
1194
            LOG_SWTLB("%s: AS doesn't match\n", __func__);
1195
            return -1;
1196
        }
1197

    
1198
        *prot = _prot;
1199
        if (_prot & PAGE_EXEC) {
1200
            LOG_SWTLB("%s: good TLB!\n", __func__);
1201
            return 0;
1202
        }
1203

    
1204
        LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
1205
        ret = -3;
1206
    } else {
1207
        if (msr_dr != (tlb->attr & 1)) {
1208
            LOG_SWTLB("%s: AS doesn't match\n", __func__);
1209
            return -1;
1210
        }
1211

    
1212
        *prot = _prot;
1213
        if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
1214
            LOG_SWTLB("%s: found TLB!\n", __func__);
1215
            return 0;
1216
        }
1217

    
1218
        LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
1219
        ret = -2;
1220
    }
1221

    
1222
    return ret;
1223
}
1224

    
1225
static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1226
                                          target_ulong address, int rw,
1227
                                          int access_type)
1228
{
1229
    ppcemb_tlb_t *tlb;
1230
    target_phys_addr_t raddr;
1231
    int i, ret;
1232

    
1233
    ret = -1;
1234
    raddr = (target_phys_addr_t)-1ULL;
1235
    for (i = 0; i < env->nb_tlb; i++) {
1236
        tlb = &env->tlb[i].tlbe;
1237
        ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
1238
                                 access_type, i);
1239
        if (!ret) {
1240
            break;
1241
        }
1242
    }
1243

    
1244
    if (ret >= 0) {
1245
        ctx->raddr = raddr;
1246
        LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1247
                  " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1248
                  ret);
1249
    } else {
1250
        LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1251
                  " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1252
    }
1253

    
1254
    return ret;
1255
}
1256

    
1257
void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
1258
{
1259
    int tlb_size;
1260
    int i, j;
1261
    ppc_tlb_t *tlb = env->tlb;
1262

    
1263
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1264
        if (flags & (1 << i)) {
1265
            tlb_size = booke206_tlb_size(env, i);
1266
            for (j = 0; j < tlb_size; j++) {
1267
                if (!check_iprot || !(tlb[j].tlbe.attr & MAS1_IPROT)) {
1268
                    tlb[j].tlbe.prot = 0;
1269
                }
1270
            }
1271
        }
1272
        tlb += booke206_tlb_size(env, i);
1273
    }
1274

    
1275
    tlb_flush(env, 1);
1276
}
1277

    
1278
static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
1279
                                        target_ulong address, int rw,
1280
                                        int access_type)
1281
{
1282
    ppcemb_tlb_t *tlb;
1283
    target_phys_addr_t raddr;
1284
    int i, j, ret;
1285

    
1286
    ret = -1;
1287
    raddr = (target_phys_addr_t)-1ULL;
1288

    
1289
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1290
        int ways = booke206_tlb_ways(env, i);
1291

    
1292
        for (j = 0; j < ways; j++) {
1293
            tlb = booke206_get_tlbe(env, i, address, j);
1294
            ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
1295
                                     access_type, j);
1296
            if (ret != -1) {
1297
                goto found_tlb;
1298
            }
1299
        }
1300
    }
1301

    
1302
found_tlb:
1303

    
1304
    if (ret >= 0) {
1305
        ctx->raddr = raddr;
1306
        LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1307
                  " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1308
                  ret);
1309
    } else {
1310
        LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1311
                  " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1312
    }
1313

    
1314
    return ret;
1315
}
1316

    
1317
static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1318
                                 target_ulong eaddr, int rw)
1319
{
1320
    int in_plb, ret;
1321

    
1322
    ctx->raddr = eaddr;
1323
    ctx->prot = PAGE_READ | PAGE_EXEC;
1324
    ret = 0;
1325
    switch (env->mmu_model) {
1326
    case POWERPC_MMU_32B:
1327
    case POWERPC_MMU_601:
1328
    case POWERPC_MMU_SOFT_6xx:
1329
    case POWERPC_MMU_SOFT_74xx:
1330
    case POWERPC_MMU_SOFT_4xx:
1331
    case POWERPC_MMU_REAL:
1332
    case POWERPC_MMU_BOOKE:
1333
        ctx->prot |= PAGE_WRITE;
1334
        break;
1335
#if defined(TARGET_PPC64)
1336
    case POWERPC_MMU_620:
1337
    case POWERPC_MMU_64B:
1338
    case POWERPC_MMU_2_06:
1339
        /* Real address are 60 bits long */
1340
        ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1341
        ctx->prot |= PAGE_WRITE;
1342
        break;
1343
#endif
1344
    case POWERPC_MMU_SOFT_4xx_Z:
1345
        if (unlikely(msr_pe != 0)) {
1346
            /* 403 family add some particular protections,
1347
             * using PBL/PBU registers for accesses with no translation.
1348
             */
1349
            in_plb =
1350
                /* Check PLB validity */
1351
                (env->pb[0] < env->pb[1] &&
1352
                 /* and address in plb area */
1353
                 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1354
                (env->pb[2] < env->pb[3] &&
1355
                 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1356
            if (in_plb ^ msr_px) {
1357
                /* Access in protected area */
1358
                if (rw == 1) {
1359
                    /* Access is not allowed */
1360
                    ret = -2;
1361
                }
1362
            } else {
1363
                /* Read-write access is allowed */
1364
                ctx->prot |= PAGE_WRITE;
1365
            }
1366
        }
1367
        break;
1368
    case POWERPC_MMU_MPC8xx:
1369
        /* XXX: TODO */
1370
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1371
        break;
1372
    case POWERPC_MMU_BOOKE206:
1373
        cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");
1374
        break;
1375
    default:
1376
        cpu_abort(env, "Unknown or invalid MMU model\n");
1377
        return -1;
1378
    }
1379

    
1380
    return ret;
1381
}
1382

    
1383
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1384
                          int rw, int access_type)
1385
{
1386
    int ret;
1387

    
1388
#if 0
1389
    qemu_log("%s\n", __func__);
1390
#endif
1391
    if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1392
        (access_type != ACCESS_CODE && msr_dr == 0)) {
1393
        if (env->mmu_model == POWERPC_MMU_BOOKE) {
1394
            /* The BookE MMU always performs address translation. The
1395
               IS and DS bits only affect the address space.  */
1396
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1397
                                                rw, access_type);
1398
        } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
1399
            ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1400
                                               access_type);
1401
        } else {
1402
            /* No address translation.  */
1403
            ret = check_physical(env, ctx, eaddr, rw);
1404
        }
1405
    } else {
1406
        ret = -1;
1407
        switch (env->mmu_model) {
1408
        case POWERPC_MMU_32B:
1409
        case POWERPC_MMU_601:
1410
        case POWERPC_MMU_SOFT_6xx:
1411
        case POWERPC_MMU_SOFT_74xx:
1412
            /* Try to find a BAT */
1413
            if (env->nb_BATs != 0)
1414
                ret = get_bat(env, ctx, eaddr, rw, access_type);
1415
#if defined(TARGET_PPC64)
1416
        case POWERPC_MMU_620:
1417
        case POWERPC_MMU_64B:
1418
        case POWERPC_MMU_2_06:
1419
#endif
1420
            if (ret < 0) {
1421
                /* We didn't match any BAT entry or don't have BATs */
1422
                ret = get_segment(env, ctx, eaddr, rw, access_type);
1423
            }
1424
            break;
1425
        case POWERPC_MMU_SOFT_4xx:
1426
        case POWERPC_MMU_SOFT_4xx_Z:
1427
            ret = mmu40x_get_physical_address(env, ctx, eaddr,
1428
                                              rw, access_type);
1429
            break;
1430
        case POWERPC_MMU_BOOKE:
1431
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1432
                                                rw, access_type);
1433
            break;
1434
        case POWERPC_MMU_BOOKE206:
1435
            ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1436
                                               access_type);
1437
            break;
1438
        case POWERPC_MMU_MPC8xx:
1439
            /* XXX: TODO */
1440
            cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1441
            break;
1442
        case POWERPC_MMU_REAL:
1443
            cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1444
            return -1;
1445
        default:
1446
            cpu_abort(env, "Unknown or invalid MMU model\n");
1447
            return -1;
1448
        }
1449
    }
1450
#if 0
1451
    qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1452
             __func__, eaddr, ret, ctx->raddr);
1453
#endif
1454

    
1455
    return ret;
1456
}
1457

    
1458
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1459
{
1460
    mmu_ctx_t ctx;
1461

    
1462
    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1463
        return -1;
1464

    
1465
    return ctx.raddr & TARGET_PAGE_MASK;
1466
}
1467

    
1468
static void booke206_update_mas_tlb_miss(CPUState *env, target_ulong address,
1469
                                     int rw)
1470
{
1471
    env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1472
    env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1473
    env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1474
    env->spr[SPR_BOOKE_MAS3] = 0;
1475
    env->spr[SPR_BOOKE_MAS6] = 0;
1476
    env->spr[SPR_BOOKE_MAS7] = 0;
1477

    
1478
    /* AS */
1479
    if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
1480
        env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1481
        env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1482
    }
1483

    
1484
    env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1485
    env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1486

    
1487
    switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1488
    case MAS4_TIDSELD_PID0:
1489
        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
1490
        break;
1491
    case MAS4_TIDSELD_PID1:
1492
        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
1493
        break;
1494
    case MAS4_TIDSELD_PID2:
1495
        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
1496
        break;
1497
    }
1498

    
1499
    env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1500

    
1501
    /* next victim logic */
1502
    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1503
    env->last_way++;
1504
    env->last_way &= booke206_tlb_ways(env, 0) - 1;
1505
    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1506
}
1507

    
1508
/* Perform address translation */
1509
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1510
                              int mmu_idx, int is_softmmu)
1511
{
1512
    mmu_ctx_t ctx;
1513
    int access_type;
1514
    int ret = 0;
1515

    
1516
    if (rw == 2) {
1517
        /* code access */
1518
        rw = 0;
1519
        access_type = ACCESS_CODE;
1520
    } else {
1521
        /* data access */
1522
        access_type = env->access_type;
1523
    }
1524
    ret = get_physical_address(env, &ctx, address, rw, access_type);
1525
    if (ret == 0) {
1526
        tlb_set_page(env, address & TARGET_PAGE_MASK,
1527
                     ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1528
                     mmu_idx, TARGET_PAGE_SIZE);
1529
        ret = 0;
1530
    } else if (ret < 0) {
1531
        LOG_MMU_STATE(env);
1532
        if (access_type == ACCESS_CODE) {
1533
            switch (ret) {
1534
            case -1:
1535
                /* No matches in page tables or TLB */
1536
                switch (env->mmu_model) {
1537
                case POWERPC_MMU_SOFT_6xx:
1538
                    env->exception_index = POWERPC_EXCP_IFTLB;
1539
                    env->error_code = 1 << 18;
1540
                    env->spr[SPR_IMISS] = address;
1541
                    env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1542
                    goto tlb_miss;
1543
                case POWERPC_MMU_SOFT_74xx:
1544
                    env->exception_index = POWERPC_EXCP_IFTLB;
1545
                    goto tlb_miss_74xx;
1546
                case POWERPC_MMU_SOFT_4xx:
1547
                case POWERPC_MMU_SOFT_4xx_Z:
1548
                    env->exception_index = POWERPC_EXCP_ITLB;
1549
                    env->error_code = 0;
1550
                    env->spr[SPR_40x_DEAR] = address;
1551
                    env->spr[SPR_40x_ESR] = 0x00000000;
1552
                    break;
1553
                case POWERPC_MMU_32B:
1554
                case POWERPC_MMU_601:
1555
#if defined(TARGET_PPC64)
1556
                case POWERPC_MMU_620:
1557
                case POWERPC_MMU_64B:
1558
                case POWERPC_MMU_2_06:
1559
#endif
1560
                    env->exception_index = POWERPC_EXCP_ISI;
1561
                    env->error_code = 0x40000000;
1562
                    break;
1563
                case POWERPC_MMU_BOOKE206:
1564
                    booke206_update_mas_tlb_miss(env, address, rw);
1565
                    /* fall through */
1566
                case POWERPC_MMU_BOOKE:
1567
                    env->exception_index = POWERPC_EXCP_ITLB;
1568
                    env->error_code = 0;
1569
                    env->spr[SPR_BOOKE_DEAR] = address;
1570
                    return -1;
1571
                case POWERPC_MMU_MPC8xx:
1572
                    /* XXX: TODO */
1573
                    cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1574
                    break;
1575
                case POWERPC_MMU_REAL:
1576
                    cpu_abort(env, "PowerPC in real mode should never raise "
1577
                              "any MMU exceptions\n");
1578
                    return -1;
1579
                default:
1580
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1581
                    return -1;
1582
                }
1583
                break;
1584
            case -2:
1585
                /* Access rights violation */
1586
                env->exception_index = POWERPC_EXCP_ISI;
1587
                env->error_code = 0x08000000;
1588
                break;
1589
            case -3:
1590
                /* No execute protection violation */
1591
                if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1592
                    (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1593
                    env->spr[SPR_BOOKE_ESR] = 0x00000000;
1594
                }
1595
                env->exception_index = POWERPC_EXCP_ISI;
1596
                env->error_code = 0x10000000;
1597
                break;
1598
            case -4:
1599
                /* Direct store exception */
1600
                /* No code fetch is allowed in direct-store areas */
1601
                env->exception_index = POWERPC_EXCP_ISI;
1602
                env->error_code = 0x10000000;
1603
                break;
1604
#if defined(TARGET_PPC64)
1605
            case -5:
1606
                /* No match in segment table */
1607
                if (env->mmu_model == POWERPC_MMU_620) {
1608
                    env->exception_index = POWERPC_EXCP_ISI;
1609
                    /* XXX: this might be incorrect */
1610
                    env->error_code = 0x40000000;
1611
                } else {
1612
                    env->exception_index = POWERPC_EXCP_ISEG;
1613
                    env->error_code = 0;
1614
                }
1615
                break;
1616
#endif
1617
            }
1618
        } else {
1619
            switch (ret) {
1620
            case -1:
1621
                /* No matches in page tables or TLB */
1622
                switch (env->mmu_model) {
1623
                case POWERPC_MMU_SOFT_6xx:
1624
                    if (rw == 1) {
1625
                        env->exception_index = POWERPC_EXCP_DSTLB;
1626
                        env->error_code = 1 << 16;
1627
                    } else {
1628
                        env->exception_index = POWERPC_EXCP_DLTLB;
1629
                        env->error_code = 0;
1630
                    }
1631
                    env->spr[SPR_DMISS] = address;
1632
                    env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1633
                tlb_miss:
1634
                    env->error_code |= ctx.key << 19;
1635
                    env->spr[SPR_HASH1] = env->htab_base +
1636
                        get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1637
                    env->spr[SPR_HASH2] = env->htab_base +
1638
                        get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1639
                    break;
1640
                case POWERPC_MMU_SOFT_74xx:
1641
                    if (rw == 1) {
1642
                        env->exception_index = POWERPC_EXCP_DSTLB;
1643
                    } else {
1644
                        env->exception_index = POWERPC_EXCP_DLTLB;
1645
                    }
1646
                tlb_miss_74xx:
1647
                    /* Implement LRU algorithm */
1648
                    env->error_code = ctx.key << 19;
1649
                    env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1650
                        ((env->last_way + 1) & (env->nb_ways - 1));
1651
                    env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1652
                    break;
1653
                case POWERPC_MMU_SOFT_4xx:
1654
                case POWERPC_MMU_SOFT_4xx_Z:
1655
                    env->exception_index = POWERPC_EXCP_DTLB;
1656
                    env->error_code = 0;
1657
                    env->spr[SPR_40x_DEAR] = address;
1658
                    if (rw)
1659
                        env->spr[SPR_40x_ESR] = 0x00800000;
1660
                    else
1661
                        env->spr[SPR_40x_ESR] = 0x00000000;
1662
                    break;
1663
                case POWERPC_MMU_32B:
1664
                case POWERPC_MMU_601:
1665
#if defined(TARGET_PPC64)
1666
                case POWERPC_MMU_620:
1667
                case POWERPC_MMU_64B:
1668
                case POWERPC_MMU_2_06:
1669
#endif
1670
                    env->exception_index = POWERPC_EXCP_DSI;
1671
                    env->error_code = 0;
1672
                    env->spr[SPR_DAR] = address;
1673
                    if (rw == 1)
1674
                        env->spr[SPR_DSISR] = 0x42000000;
1675
                    else
1676
                        env->spr[SPR_DSISR] = 0x40000000;
1677
                    break;
1678
                case POWERPC_MMU_MPC8xx:
1679
                    /* XXX: TODO */
1680
                    cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1681
                    break;
1682
                case POWERPC_MMU_BOOKE206:
1683
                    booke206_update_mas_tlb_miss(env, address, rw);
1684
                    /* fall through */
1685
                case POWERPC_MMU_BOOKE:
1686
                    env->exception_index = POWERPC_EXCP_DTLB;
1687
                    env->error_code = 0;
1688
                    env->spr[SPR_BOOKE_DEAR] = address;
1689
                    env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1690
                    return -1;
1691
                case POWERPC_MMU_REAL:
1692
                    cpu_abort(env, "PowerPC in real mode should never raise "
1693
                              "any MMU exceptions\n");
1694
                    return -1;
1695
                default:
1696
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1697
                    return -1;
1698
                }
1699
                break;
1700
            case -2:
1701
                /* Access rights violation */
1702
                env->exception_index = POWERPC_EXCP_DSI;
1703
                env->error_code = 0;
1704
                if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1705
                    || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1706
                    env->spr[SPR_40x_DEAR] = address;
1707
                    if (rw) {
1708
                        env->spr[SPR_40x_ESR] |= 0x00800000;
1709
                    }
1710
                } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1711
                           (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1712
                    env->spr[SPR_BOOKE_DEAR] = address;
1713
                    env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1714
                } else {
1715
                    env->spr[SPR_DAR] = address;
1716
                    if (rw == 1) {
1717
                        env->spr[SPR_DSISR] = 0x0A000000;
1718
                    } else {
1719
                        env->spr[SPR_DSISR] = 0x08000000;
1720
                    }
1721
                }
1722
                break;
1723
            case -4:
1724
                /* Direct store exception */
1725
                switch (access_type) {
1726
                case ACCESS_FLOAT:
1727
                    /* Floating point load/store */
1728
                    env->exception_index = POWERPC_EXCP_ALIGN;
1729
                    env->error_code = POWERPC_EXCP_ALIGN_FP;
1730
                    env->spr[SPR_DAR] = address;
1731
                    break;
1732
                case ACCESS_RES:
1733
                    /* lwarx, ldarx or stwcx. */
1734
                    env->exception_index = POWERPC_EXCP_DSI;
1735
                    env->error_code = 0;
1736
                    env->spr[SPR_DAR] = address;
1737
                    if (rw == 1)
1738
                        env->spr[SPR_DSISR] = 0x06000000;
1739
                    else
1740
                        env->spr[SPR_DSISR] = 0x04000000;
1741
                    break;
1742
                case ACCESS_EXT:
1743
                    /* eciwx or ecowx */
1744
                    env->exception_index = POWERPC_EXCP_DSI;
1745
                    env->error_code = 0;
1746
                    env->spr[SPR_DAR] = address;
1747
                    if (rw == 1)
1748
                        env->spr[SPR_DSISR] = 0x06100000;
1749
                    else
1750
                        env->spr[SPR_DSISR] = 0x04100000;
1751
                    break;
1752
                default:
1753
                    printf("DSI: invalid exception (%d)\n", ret);
1754
                    env->exception_index = POWERPC_EXCP_PROGRAM;
1755
                    env->error_code =
1756
                        POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1757
                    env->spr[SPR_DAR] = address;
1758
                    break;
1759
                }
1760
                break;
1761
#if defined(TARGET_PPC64)
1762
            case -5:
1763
                /* No match in segment table */
1764
                if (env->mmu_model == POWERPC_MMU_620) {
1765
                    env->exception_index = POWERPC_EXCP_DSI;
1766
                    env->error_code = 0;
1767
                    env->spr[SPR_DAR] = address;
1768
                    /* XXX: this might be incorrect */
1769
                    if (rw == 1)
1770
                        env->spr[SPR_DSISR] = 0x42000000;
1771
                    else
1772
                        env->spr[SPR_DSISR] = 0x40000000;
1773
                } else {
1774
                    env->exception_index = POWERPC_EXCP_DSEG;
1775
                    env->error_code = 0;
1776
                    env->spr[SPR_DAR] = address;
1777
                }
1778
                break;
1779
#endif
1780
            }
1781
        }
1782
#if 0
1783
        printf("%s: set exception to %d %02x\n", __func__,
1784
               env->exception, env->error_code);
1785
#endif
1786
        ret = 1;
1787
    }
1788

    
1789
    return ret;
1790
}
1791

    
1792
/*****************************************************************************/
1793
/* BATs management */
1794
#if !defined(FLUSH_ALL_TLBS)
1795
static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1796
                                     target_ulong mask)
1797
{
1798
    target_ulong base, end, page;
1799

    
1800
    base = BATu & ~0x0001FFFF;
1801
    end = base + mask + 0x00020000;
1802
    LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1803
             TARGET_FMT_lx ")\n", base, end, mask);
1804
    for (page = base; page != end; page += TARGET_PAGE_SIZE)
1805
        tlb_flush_page(env, page);
1806
    LOG_BATS("Flush done\n");
1807
}
1808
#endif
1809

    
1810
static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1811
                                  target_ulong value)
1812
{
1813
    LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1814
             nr, ul == 0 ? 'u' : 'l', value, env->nip);
1815
}
1816

    
1817
void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1818
{
1819
    target_ulong mask;
1820

    
1821
    dump_store_bat(env, 'I', 0, nr, value);
1822
    if (env->IBAT[0][nr] != value) {
1823
        mask = (value << 15) & 0x0FFE0000UL;
1824
#if !defined(FLUSH_ALL_TLBS)
1825
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1826
#endif
1827
        /* When storing valid upper BAT, mask BEPI and BRPN
1828
         * and invalidate all TLBs covered by this BAT
1829
         */
1830
        mask = (value << 15) & 0x0FFE0000UL;
1831
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1832
            (value & ~0x0001FFFFUL & ~mask);
1833
        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1834
            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1835
#if !defined(FLUSH_ALL_TLBS)
1836
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1837
#else
1838
        tlb_flush(env, 1);
1839
#endif
1840
    }
1841
}
1842

    
1843
void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1844
{
1845
    dump_store_bat(env, 'I', 1, nr, value);
1846
    env->IBAT[1][nr] = value;
1847
}
1848

    
1849
void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1850
{
1851
    target_ulong mask;
1852

    
1853
    dump_store_bat(env, 'D', 0, nr, value);
1854
    if (env->DBAT[0][nr] != value) {
1855
        /* When storing valid upper BAT, mask BEPI and BRPN
1856
         * and invalidate all TLBs covered by this BAT
1857
         */
1858
        mask = (value << 15) & 0x0FFE0000UL;
1859
#if !defined(FLUSH_ALL_TLBS)
1860
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1861
#endif
1862
        mask = (value << 15) & 0x0FFE0000UL;
1863
        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1864
            (value & ~0x0001FFFFUL & ~mask);
1865
        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1866
            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1867
#if !defined(FLUSH_ALL_TLBS)
1868
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1869
#else
1870
        tlb_flush(env, 1);
1871
#endif
1872
    }
1873
}
1874

    
1875
void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1876
{
1877
    dump_store_bat(env, 'D', 1, nr, value);
1878
    env->DBAT[1][nr] = value;
1879
}
1880

    
1881
void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1882
{
1883
    target_ulong mask;
1884
#if defined(FLUSH_ALL_TLBS)
1885
    int do_inval;
1886
#endif
1887

    
1888
    dump_store_bat(env, 'I', 0, nr, value);
1889
    if (env->IBAT[0][nr] != value) {
1890
#if defined(FLUSH_ALL_TLBS)
1891
        do_inval = 0;
1892
#endif
1893
        mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1894
        if (env->IBAT[1][nr] & 0x40) {
1895
            /* Invalidate BAT only if it is valid */
1896
#if !defined(FLUSH_ALL_TLBS)
1897
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1898
#else
1899
            do_inval = 1;
1900
#endif
1901
        }
1902
        /* When storing valid upper BAT, mask BEPI and BRPN
1903
         * and invalidate all TLBs covered by this BAT
1904
         */
1905
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1906
            (value & ~0x0001FFFFUL & ~mask);
1907
        env->DBAT[0][nr] = env->IBAT[0][nr];
1908
        if (env->IBAT[1][nr] & 0x40) {
1909
#if !defined(FLUSH_ALL_TLBS)
1910
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1911
#else
1912
            do_inval = 1;
1913
#endif
1914
        }
1915
#if defined(FLUSH_ALL_TLBS)
1916
        if (do_inval)
1917
            tlb_flush(env, 1);
1918
#endif
1919
    }
1920
}
1921

    
1922
void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1923
{
1924
    target_ulong mask;
1925
#if defined(FLUSH_ALL_TLBS)
1926
    int do_inval;
1927
#endif
1928

    
1929
    dump_store_bat(env, 'I', 1, nr, value);
1930
    if (env->IBAT[1][nr] != value) {
1931
#if defined(FLUSH_ALL_TLBS)
1932
        do_inval = 0;
1933
#endif
1934
        if (env->IBAT[1][nr] & 0x40) {
1935
#if !defined(FLUSH_ALL_TLBS)
1936
            mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1937
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1938
#else
1939
            do_inval = 1;
1940
#endif
1941
        }
1942
        if (value & 0x40) {
1943
#if !defined(FLUSH_ALL_TLBS)
1944
            mask = (value << 17) & 0x0FFE0000UL;
1945
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1946
#else
1947
            do_inval = 1;
1948
#endif
1949
        }
1950
        env->IBAT[1][nr] = value;
1951
        env->DBAT[1][nr] = value;
1952
#if defined(FLUSH_ALL_TLBS)
1953
        if (do_inval)
1954
            tlb_flush(env, 1);
1955
#endif
1956
    }
1957
}
1958

    
1959
/*****************************************************************************/
1960
/* TLB management */
1961
void ppc_tlb_invalidate_all (CPUPPCState *env)
1962
{
1963
    switch (env->mmu_model) {
1964
    case POWERPC_MMU_SOFT_6xx:
1965
    case POWERPC_MMU_SOFT_74xx:
1966
        ppc6xx_tlb_invalidate_all(env);
1967
        break;
1968
    case POWERPC_MMU_SOFT_4xx:
1969
    case POWERPC_MMU_SOFT_4xx_Z:
1970
        ppc4xx_tlb_invalidate_all(env);
1971
        break;
1972
    case POWERPC_MMU_REAL:
1973
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1974
        break;
1975
    case POWERPC_MMU_MPC8xx:
1976
        /* XXX: TODO */
1977
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1978
        break;
1979
    case POWERPC_MMU_BOOKE:
1980
        tlb_flush(env, 1);
1981
        break;
1982
    case POWERPC_MMU_BOOKE206:
1983
        booke206_flush_tlb(env, -1, 0);
1984
        break;
1985
    case POWERPC_MMU_32B:
1986
    case POWERPC_MMU_601:
1987
#if defined(TARGET_PPC64)
1988
    case POWERPC_MMU_620:
1989
    case POWERPC_MMU_64B:
1990
    case POWERPC_MMU_2_06:
1991
#endif /* defined(TARGET_PPC64) */
1992
        tlb_flush(env, 1);
1993
        break;
1994
    default:
1995
        /* XXX: TODO */
1996
        cpu_abort(env, "Unknown MMU model\n");
1997
        break;
1998
    }
1999
}
2000

    
2001
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
2002
{
2003
#if !defined(FLUSH_ALL_TLBS)
2004
    addr &= TARGET_PAGE_MASK;
2005
    switch (env->mmu_model) {
2006
    case POWERPC_MMU_SOFT_6xx:
2007
    case POWERPC_MMU_SOFT_74xx:
2008
        ppc6xx_tlb_invalidate_virt(env, addr, 0);
2009
        if (env->id_tlbs == 1)
2010
            ppc6xx_tlb_invalidate_virt(env, addr, 1);
2011
        break;
2012
    case POWERPC_MMU_SOFT_4xx:
2013
    case POWERPC_MMU_SOFT_4xx_Z:
2014
        ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
2015
        break;
2016
    case POWERPC_MMU_REAL:
2017
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2018
        break;
2019
    case POWERPC_MMU_MPC8xx:
2020
        /* XXX: TODO */
2021
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2022
        break;
2023
    case POWERPC_MMU_BOOKE:
2024
        /* XXX: TODO */
2025
        cpu_abort(env, "BookE MMU model is not implemented\n");
2026
        break;
2027
    case POWERPC_MMU_BOOKE206:
2028
        /* XXX: TODO */
2029
        cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
2030
        break;
2031
    case POWERPC_MMU_32B:
2032
    case POWERPC_MMU_601:
2033
        /* tlbie invalidate TLBs for all segments */
2034
        addr &= ~((target_ulong)-1ULL << 28);
2035
        /* XXX: this case should be optimized,
2036
         * giving a mask to tlb_flush_page
2037
         */
2038
        tlb_flush_page(env, addr | (0x0 << 28));
2039
        tlb_flush_page(env, addr | (0x1 << 28));
2040
        tlb_flush_page(env, addr | (0x2 << 28));
2041
        tlb_flush_page(env, addr | (0x3 << 28));
2042
        tlb_flush_page(env, addr | (0x4 << 28));
2043
        tlb_flush_page(env, addr | (0x5 << 28));
2044
        tlb_flush_page(env, addr | (0x6 << 28));
2045
        tlb_flush_page(env, addr | (0x7 << 28));
2046
        tlb_flush_page(env, addr | (0x8 << 28));
2047
        tlb_flush_page(env, addr | (0x9 << 28));
2048
        tlb_flush_page(env, addr | (0xA << 28));
2049
        tlb_flush_page(env, addr | (0xB << 28));
2050
        tlb_flush_page(env, addr | (0xC << 28));
2051
        tlb_flush_page(env, addr | (0xD << 28));
2052
        tlb_flush_page(env, addr | (0xE << 28));
2053
        tlb_flush_page(env, addr | (0xF << 28));
2054
        break;
2055
#if defined(TARGET_PPC64)
2056
    case POWERPC_MMU_620:
2057
    case POWERPC_MMU_64B:
2058
    case POWERPC_MMU_2_06:
2059
        /* tlbie invalidate TLBs for all segments */
2060
        /* XXX: given the fact that there are too many segments to invalidate,
2061
         *      and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
2062
         *      we just invalidate all TLBs
2063
         */
2064
        tlb_flush(env, 1);
2065
        break;
2066
#endif /* defined(TARGET_PPC64) */
2067
    default:
2068
        /* XXX: TODO */
2069
        cpu_abort(env, "Unknown MMU model\n");
2070
        break;
2071
    }
2072
#else
2073
    ppc_tlb_invalidate_all(env);
2074
#endif
2075
}
2076

    
2077
/*****************************************************************************/
2078
/* Special registers manipulation */
2079
#if defined(TARGET_PPC64)
2080
void ppc_store_asr (CPUPPCState *env, target_ulong value)
2081
{
2082
    if (env->asr != value) {
2083
        env->asr = value;
2084
        tlb_flush(env, 1);
2085
    }
2086
}
2087
#endif
2088

    
2089
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
2090
{
2091
    LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
2092
    if (env->spr[SPR_SDR1] != value) {
2093
        env->spr[SPR_SDR1] = value;
2094
#if defined(TARGET_PPC64)
2095
        if (env->mmu_model & POWERPC_MMU_64) {
2096
            target_ulong htabsize = value & SDR_64_HTABSIZE;
2097

    
2098
            if (htabsize > 28) {
2099
                fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2100
                        " stored in SDR1\n", htabsize);
2101
                htabsize = 28;
2102
            }
2103
            env->htab_mask = (1ULL << (htabsize + 18)) - 1;
2104
            env->htab_base = value & SDR_64_HTABORG;
2105
        } else
2106
#endif /* defined(TARGET_PPC64) */
2107
        {
2108
            /* FIXME: Should check for valid HTABMASK values */
2109
            env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
2110
            env->htab_base = value & SDR_32_HTABORG;
2111
        }
2112
        tlb_flush(env, 1);
2113
    }
2114
}
2115

    
2116
#if defined(TARGET_PPC64)
2117
target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
2118
{
2119
    // XXX
2120
    return 0;
2121
}
2122
#endif
2123

    
2124
void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
2125
{
2126
    LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2127
            srnum, value, env->sr[srnum]);
2128
#if defined(TARGET_PPC64)
2129
    if (env->mmu_model & POWERPC_MMU_64) {
2130
        uint64_t rb = 0, rs = 0;
2131

    
2132
        /* ESID = srnum */
2133
        rb |= ((uint32_t)srnum & 0xf) << 28;
2134
        /* Set the valid bit */
2135
        rb |= 1 << 27;
2136
        /* Index = ESID */
2137
        rb |= (uint32_t)srnum;
2138

    
2139
        /* VSID = VSID */
2140
        rs |= (value & 0xfffffff) << 12;
2141
        /* flags = flags */
2142
        rs |= ((value >> 27) & 0xf) << 8;
2143

    
2144
        ppc_store_slb(env, rb, rs);
2145
    } else
2146
#endif
2147
    if (env->sr[srnum] != value) {
2148
        env->sr[srnum] = value;
2149
/* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2150
   flusing the whole TLB. */
2151
#if !defined(FLUSH_ALL_TLBS) && 0
2152
        {
2153
            target_ulong page, end;
2154
            /* Invalidate 256 MB of virtual memory */
2155
            page = (16 << 20) * srnum;
2156
            end = page + (16 << 20);
2157
            for (; page != end; page += TARGET_PAGE_SIZE)
2158
                tlb_flush_page(env, page);
2159
        }
2160
#else
2161
        tlb_flush(env, 1);
2162
#endif
2163
    }
2164
}
2165
#endif /* !defined (CONFIG_USER_ONLY) */
2166

    
2167
/* GDBstub can read and write MSR... */
2168
void ppc_store_msr (CPUPPCState *env, target_ulong value)
2169
{
2170
    hreg_store_msr(env, value, 0);
2171
}
2172

    
2173
/*****************************************************************************/
2174
/* Exception processing */
2175
#if defined (CONFIG_USER_ONLY)
2176
void do_interrupt (CPUState *env)
2177
{
2178
    env->exception_index = POWERPC_EXCP_NONE;
2179
    env->error_code = 0;
2180
}
2181

    
2182
void ppc_hw_interrupt (CPUState *env)
2183
{
2184
    env->exception_index = POWERPC_EXCP_NONE;
2185
    env->error_code = 0;
2186
}
2187
#else /* defined (CONFIG_USER_ONLY) */
2188
static inline void dump_syscall(CPUState *env)
2189
{
2190
    qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2191
                  " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2192
                  " nip=" TARGET_FMT_lx "\n",
2193
                  ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2194
                  ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2195
                  ppc_dump_gpr(env, 6), env->nip);
2196
}
2197

    
2198
/* Note that this function should be greatly optimized
2199
 * when called with a constant excp, from ppc_hw_interrupt
2200
 */
2201
static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2202
{
2203
    target_ulong msr, new_msr, vector;
2204
    int srr0, srr1, asrr0, asrr1;
2205
    int lpes0, lpes1, lev;
2206

    
2207
    if (0) {
2208
        /* XXX: find a suitable condition to enable the hypervisor mode */
2209
        lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2210
        lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2211
    } else {
2212
        /* Those values ensure we won't enter the hypervisor mode */
2213
        lpes0 = 0;
2214
        lpes1 = 1;
2215
    }
2216

    
2217
    qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
2218
                  " => %08x (%02x)\n", env->nip, excp, env->error_code);
2219

    
2220
    /* new srr1 value excluding must-be-zero bits */
2221
    msr = env->msr & ~0x783f0000ULL;
2222

    
2223
    /* new interrupt handler msr */
2224
    new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2225

    
2226
    /* target registers */
2227
    srr0 = SPR_SRR0;
2228
    srr1 = SPR_SRR1;
2229
    asrr0 = -1;
2230
    asrr1 = -1;
2231

    
2232
    switch (excp) {
2233
    case POWERPC_EXCP_NONE:
2234
        /* Should never happen */
2235
        return;
2236
    case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
2237
        switch (excp_model) {
2238
        case POWERPC_EXCP_40x:
2239
            srr0 = SPR_40x_SRR2;
2240
            srr1 = SPR_40x_SRR3;
2241
            break;
2242
        case POWERPC_EXCP_BOOKE:
2243
            srr0 = SPR_BOOKE_CSRR0;
2244
            srr1 = SPR_BOOKE_CSRR1;
2245
            break;
2246
        case POWERPC_EXCP_G2:
2247
            break;
2248
        default:
2249
            goto excp_invalid;
2250
        }
2251
        goto store_next;
2252
    case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
2253
        if (msr_me == 0) {
2254
            /* Machine check exception is not enabled.
2255
             * Enter checkstop state.
2256
             */
2257
            if (qemu_log_enabled()) {
2258
                qemu_log("Machine check while not allowed. "
2259
                        "Entering checkstop state\n");
2260
            } else {
2261
                fprintf(stderr, "Machine check while not allowed. "
2262
                        "Entering checkstop state\n");
2263
            }
2264
            env->halted = 1;
2265
            env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2266
        }
2267
        if (0) {
2268
            /* XXX: find a suitable condition to enable the hypervisor mode */
2269
            new_msr |= (target_ulong)MSR_HVB;
2270
        }
2271

    
2272
        /* machine check exceptions don't have ME set */
2273
        new_msr &= ~((target_ulong)1 << MSR_ME);
2274

    
2275
        /* XXX: should also have something loaded in DAR / DSISR */
2276
        switch (excp_model) {
2277
        case POWERPC_EXCP_40x:
2278
            srr0 = SPR_40x_SRR2;
2279
            srr1 = SPR_40x_SRR3;
2280
            break;
2281
        case POWERPC_EXCP_BOOKE:
2282
            srr0 = SPR_BOOKE_MCSRR0;
2283
            srr1 = SPR_BOOKE_MCSRR1;
2284
            asrr0 = SPR_BOOKE_CSRR0;
2285
            asrr1 = SPR_BOOKE_CSRR1;
2286
            break;
2287
        default:
2288
            break;
2289
        }
2290
        goto store_next;
2291
    case POWERPC_EXCP_DSI:       /* Data storage exception                   */
2292
        LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2293
                 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2294
        if (lpes1 == 0)
2295
            new_msr |= (target_ulong)MSR_HVB;
2296
        goto store_next;
2297
    case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
2298
        LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2299
                 "\n", msr, env->nip);
2300
        if (lpes1 == 0)
2301
            new_msr |= (target_ulong)MSR_HVB;
2302
        msr |= env->error_code;
2303
        goto store_next;
2304
    case POWERPC_EXCP_EXTERNAL:  /* External input                           */
2305
        if (lpes0 == 1)
2306
            new_msr |= (target_ulong)MSR_HVB;
2307
        goto store_next;
2308
    case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
2309
        if (lpes1 == 0)
2310
            new_msr |= (target_ulong)MSR_HVB;
2311
        /* XXX: this is false */
2312
        /* Get rS/rD and rA from faulting opcode */
2313
        env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2314
        goto store_current;
2315
    case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
2316
        switch (env->error_code & ~0xF) {
2317
        case POWERPC_EXCP_FP:
2318
            if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2319
                LOG_EXCP("Ignore floating point exception\n");
2320
                env->exception_index = POWERPC_EXCP_NONE;
2321
                env->error_code = 0;
2322
                return;
2323
            }
2324
            if (lpes1 == 0)
2325
                new_msr |= (target_ulong)MSR_HVB;
2326
            msr |= 0x00100000;
2327
            if (msr_fe0 == msr_fe1)
2328
                goto store_next;
2329
            msr |= 0x00010000;
2330
            break;
2331
        case POWERPC_EXCP_INVAL:
2332
            LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2333
            if (lpes1 == 0)
2334
                new_msr |= (target_ulong)MSR_HVB;
2335
            msr |= 0x00080000;
2336
            break;
2337
        case POWERPC_EXCP_PRIV:
2338
            if (lpes1 == 0)
2339
                new_msr |= (target_ulong)MSR_HVB;
2340
            msr |= 0x00040000;
2341
            break;
2342
        case POWERPC_EXCP_TRAP:
2343
            if (lpes1 == 0)
2344
                new_msr |= (target_ulong)MSR_HVB;
2345
            msr |= 0x00020000;
2346
            break;
2347
        default:
2348
            /* Should never occur */
2349
            cpu_abort(env, "Invalid program exception %d. Aborting\n",
2350
                      env->error_code);
2351
            break;
2352
        }
2353
        goto store_current;
2354
    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
2355
        if (lpes1 == 0)
2356
            new_msr |= (target_ulong)MSR_HVB;
2357
        goto store_current;
2358
    case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
2359
        dump_syscall(env);
2360
        lev = env->error_code;
2361
        if ((lev == 1) && cpu_ppc_hypercall) {
2362
            cpu_ppc_hypercall(env);
2363
            return;
2364
        }
2365
        if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2366
            new_msr |= (target_ulong)MSR_HVB;
2367
        goto store_next;
2368
    case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
2369
        goto store_current;
2370
    case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
2371
        if (lpes1 == 0)
2372
            new_msr |= (target_ulong)MSR_HVB;
2373
        goto store_next;
2374
    case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
2375
        /* FIT on 4xx */
2376
        LOG_EXCP("FIT exception\n");
2377
        goto store_next;
2378
    case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
2379
        LOG_EXCP("WDT exception\n");
2380
        switch (excp_model) {
2381
        case POWERPC_EXCP_BOOKE:
2382
            srr0 = SPR_BOOKE_CSRR0;
2383
            srr1 = SPR_BOOKE_CSRR1;
2384
            break;
2385
        default:
2386
            break;
2387
        }
2388
        goto store_next;
2389
    case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
2390
        goto store_next;
2391
    case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
2392
        goto store_next;
2393
    case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
2394
        switch (excp_model) {
2395
        case POWERPC_EXCP_BOOKE:
2396
            srr0 = SPR_BOOKE_DSRR0;
2397
            srr1 = SPR_BOOKE_DSRR1;
2398
            asrr0 = SPR_BOOKE_CSRR0;
2399
            asrr1 = SPR_BOOKE_CSRR1;
2400
            break;
2401
        default:
2402
            break;
2403
        }
2404
        /* XXX: TODO */
2405
        cpu_abort(env, "Debug exception is not implemented yet !\n");
2406
        goto store_next;
2407
    case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
2408
        goto store_current;
2409
    case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
2410
        /* XXX: TODO */
2411
        cpu_abort(env, "Embedded floating point data exception "
2412
                  "is not implemented yet !\n");
2413
        goto store_next;
2414
    case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
2415
        /* XXX: TODO */
2416
        cpu_abort(env, "Embedded floating point round exception "
2417
                  "is not implemented yet !\n");
2418
        goto store_next;
2419
    case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
2420
        /* XXX: TODO */
2421
        cpu_abort(env,
2422
                  "Performance counter exception is not implemented yet !\n");
2423
        goto store_next;
2424
    case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
2425
        /* XXX: TODO */
2426
        cpu_abort(env,
2427
                  "Embedded doorbell interrupt is not implemented yet !\n");
2428
        goto store_next;
2429
    case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
2430
        switch (excp_model) {
2431
        case POWERPC_EXCP_BOOKE:
2432
            srr0 = SPR_BOOKE_CSRR0;
2433
            srr1 = SPR_BOOKE_CSRR1;
2434
            break;
2435
        default:
2436
            break;
2437
        }
2438
        /* XXX: TODO */
2439
        cpu_abort(env, "Embedded doorbell critical interrupt "
2440
                  "is not implemented yet !\n");
2441
        goto store_next;
2442
    case POWERPC_EXCP_RESET:     /* System reset exception                   */
2443
        if (msr_pow) {
2444
            /* indicate that we resumed from power save mode */
2445
            msr |= 0x10000;
2446
        } else {
2447
            new_msr &= ~((target_ulong)1 << MSR_ME);
2448
        }
2449

    
2450
        if (0) {
2451
            /* XXX: find a suitable condition to enable the hypervisor mode */
2452
            new_msr |= (target_ulong)MSR_HVB;
2453
        }
2454
        goto store_next;
2455
    case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
2456
        if (lpes1 == 0)
2457
            new_msr |= (target_ulong)MSR_HVB;
2458
        goto store_next;
2459
    case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
2460
        if (lpes1 == 0)
2461
            new_msr |= (target_ulong)MSR_HVB;
2462
        goto store_next;
2463
    case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
2464
        srr0 = SPR_HSRR0;
2465
        srr1 = SPR_HSRR1;
2466
        new_msr |= (target_ulong)MSR_HVB;
2467
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2468
        goto store_next;
2469
    case POWERPC_EXCP_TRACE:     /* Trace exception                          */
2470
        if (lpes1 == 0)
2471
            new_msr |= (target_ulong)MSR_HVB;
2472
        goto store_next;
2473
    case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
2474
        srr0 = SPR_HSRR0;
2475
        srr1 = SPR_HSRR1;
2476
        new_msr |= (target_ulong)MSR_HVB;
2477
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2478
        goto store_next;
2479
    case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
2480
        srr0 = SPR_HSRR0;
2481
        srr1 = SPR_HSRR1;
2482
        new_msr |= (target_ulong)MSR_HVB;
2483
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2484
        goto store_next;
2485
    case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
2486
        srr0 = SPR_HSRR0;
2487
        srr1 = SPR_HSRR1;
2488
        new_msr |= (target_ulong)MSR_HVB;
2489
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2490
        goto store_next;
2491
    case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
2492
        srr0 = SPR_HSRR0;
2493
        srr1 = SPR_HSRR1;
2494
        new_msr |= (target_ulong)MSR_HVB;
2495
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2496
        goto store_next;
2497
    case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
2498
        if (lpes1 == 0)
2499
            new_msr |= (target_ulong)MSR_HVB;
2500
        goto store_current;
2501
    case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
2502
        LOG_EXCP("PIT exception\n");
2503
        goto store_next;
2504
    case POWERPC_EXCP_IO:        /* IO error exception                       */
2505
        /* XXX: TODO */
2506
        cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2507
        goto store_next;
2508
    case POWERPC_EXCP_RUNM:      /* Run mode exception                       */
2509
        /* XXX: TODO */
2510
        cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2511
        goto store_next;
2512
    case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 */
2513
        /* XXX: TODO */
2514
        cpu_abort(env, "602 emulation trap exception "
2515
                  "is not implemented yet !\n");
2516
        goto store_next;
2517
    case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
2518
        if (lpes1 == 0) /* XXX: check this */
2519
            new_msr |= (target_ulong)MSR_HVB;
2520
        switch (excp_model) {
2521
        case POWERPC_EXCP_602:
2522
        case POWERPC_EXCP_603:
2523
        case POWERPC_EXCP_603E:
2524
        case POWERPC_EXCP_G2:
2525
            goto tlb_miss_tgpr;
2526
        case POWERPC_EXCP_7x5:
2527
            goto tlb_miss;
2528
        case POWERPC_EXCP_74xx:
2529
            goto tlb_miss_74xx;
2530
        default:
2531
            cpu_abort(env, "Invalid instruction TLB miss exception\n");
2532
            break;
2533
        }
2534
        break;
2535
    case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
2536
        if (lpes1 == 0) /* XXX: check this */
2537
            new_msr |= (target_ulong)MSR_HVB;
2538
        switch (excp_model) {
2539
        case POWERPC_EXCP_602:
2540
        case POWERPC_EXCP_603:
2541
        case POWERPC_EXCP_603E:
2542
        case POWERPC_EXCP_G2:
2543
            goto tlb_miss_tgpr;
2544
        case POWERPC_EXCP_7x5:
2545
            goto tlb_miss;
2546
        case POWERPC_EXCP_74xx:
2547
            goto tlb_miss_74xx;
2548
        default:
2549
            cpu_abort(env, "Invalid data load TLB miss exception\n");
2550
            break;
2551
        }
2552
        break;
2553
    case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
2554
        if (lpes1 == 0) /* XXX: check this */
2555
            new_msr |= (target_ulong)MSR_HVB;
2556
        switch (excp_model) {
2557
        case POWERPC_EXCP_602:
2558
        case POWERPC_EXCP_603:
2559
        case POWERPC_EXCP_603E:
2560
        case POWERPC_EXCP_G2:
2561
        tlb_miss_tgpr:
2562
            /* Swap temporary saved registers with GPRs */
2563
            if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2564
                new_msr |= (target_ulong)1 << MSR_TGPR;
2565
                hreg_swap_gpr_tgpr(env);
2566
            }
2567
            goto tlb_miss;
2568
        case POWERPC_EXCP_7x5:
2569
        tlb_miss:
2570
#if defined (DEBUG_SOFTWARE_TLB)
2571
            if (qemu_log_enabled()) {
2572
                const char *es;
2573
                target_ulong *miss, *cmp;
2574
                int en;
2575
                if (excp == POWERPC_EXCP_IFTLB) {
2576
                    es = "I";
2577
                    en = 'I';
2578
                    miss = &env->spr[SPR_IMISS];
2579
                    cmp = &env->spr[SPR_ICMP];
2580
                } else {
2581
                    if (excp == POWERPC_EXCP_DLTLB)
2582
                        es = "DL";
2583
                    else
2584
                        es = "DS";
2585
                    en = 'D';
2586
                    miss = &env->spr[SPR_DMISS];
2587
                    cmp = &env->spr[SPR_DCMP];
2588
                }
2589
                qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2590
                         TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2591
                         TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2592
                         env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2593
                         env->error_code);
2594
            }
2595
#endif
2596
            msr |= env->crf[0] << 28;
2597
            msr |= env->error_code; /* key, D/I, S/L bits */
2598
            /* Set way using a LRU mechanism */
2599
            msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2600
            break;
2601
        case POWERPC_EXCP_74xx:
2602
        tlb_miss_74xx:
2603
#if defined (DEBUG_SOFTWARE_TLB)
2604
            if (qemu_log_enabled()) {
2605
                const char *es;
2606
                target_ulong *miss, *cmp;
2607
                int en;
2608
                if (excp == POWERPC_EXCP_IFTLB) {
2609
                    es = "I";
2610
                    en = 'I';
2611
                    miss = &env->spr[SPR_TLBMISS];
2612
                    cmp = &env->spr[SPR_PTEHI];
2613
                } else {
2614
                    if (excp == POWERPC_EXCP_DLTLB)
2615
                        es = "DL";
2616
                    else
2617
                        es = "DS";
2618
                    en = 'D';
2619
                    miss = &env->spr[SPR_TLBMISS];
2620
                    cmp = &env->spr[SPR_PTEHI];
2621
                }
2622
                qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2623
                         TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2624
                         env->error_code);
2625
            }
2626
#endif
2627
            msr |= env->error_code; /* key bit */
2628
            break;
2629
        default:
2630
            cpu_abort(env, "Invalid data store TLB miss exception\n");
2631
            break;
2632
        }
2633
        goto store_next;
2634
    case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
2635
        /* XXX: TODO */
2636
        cpu_abort(env, "Floating point assist exception "
2637
                  "is not implemented yet !\n");
2638
        goto store_next;
2639
    case POWERPC_EXCP_DABR:      /* Data address breakpoint                  */
2640
        /* XXX: TODO */
2641
        cpu_abort(env, "DABR exception is not implemented yet !\n");
2642
        goto store_next;
2643
    case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
2644
        /* XXX: TODO */
2645
        cpu_abort(env, "IABR exception is not implemented yet !\n");
2646
        goto store_next;
2647
    case POWERPC_EXCP_SMI:       /* System management interrupt              */
2648
        /* XXX: TODO */
2649
        cpu_abort(env, "SMI exception is not implemented yet !\n");
2650
        goto store_next;
2651
    case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
2652
        /* XXX: TODO */
2653
        cpu_abort(env, "Thermal management exception "
2654
                  "is not implemented yet !\n");
2655
        goto store_next;
2656
    case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
2657
        if (lpes1 == 0)
2658
            new_msr |= (target_ulong)MSR_HVB;
2659
        /* XXX: TODO */
2660
        cpu_abort(env,
2661
                  "Performance counter exception is not implemented yet !\n");
2662
        goto store_next;
2663
    case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
2664
        /* XXX: TODO */
2665
        cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2666
        goto store_next;
2667
    case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
2668
        /* XXX: TODO */
2669
        cpu_abort(env,
2670
                  "970 soft-patch exception is not implemented yet !\n");
2671
        goto store_next;
2672
    case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
2673
        /* XXX: TODO */
2674
        cpu_abort(env,
2675
                  "970 maintenance exception is not implemented yet !\n");
2676
        goto store_next;
2677
    case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             */
2678
        /* XXX: TODO */
2679
        cpu_abort(env, "Maskable external exception "
2680
                  "is not implemented yet !\n");
2681
        goto store_next;
2682
    case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         */
2683
        /* XXX: TODO */
2684
        cpu_abort(env, "Non maskable external exception "
2685
                  "is not implemented yet !\n");
2686
        goto store_next;
2687
    default:
2688
    excp_invalid:
2689
        cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2690
        break;
2691
    store_current:
2692
        /* save current instruction location */
2693
        env->spr[srr0] = env->nip - 4;
2694
        break;
2695
    store_next:
2696
        /* save next instruction location */
2697
        env->spr[srr0] = env->nip;
2698
        break;
2699
    }
2700
    /* Save MSR */
2701
    env->spr[srr1] = msr;
2702
    /* If any alternate SRR register are defined, duplicate saved values */
2703
    if (asrr0 != -1)
2704
        env->spr[asrr0] = env->spr[srr0];
2705
    if (asrr1 != -1)
2706
        env->spr[asrr1] = env->spr[srr1];
2707
    /* If we disactivated any translation, flush TLBs */
2708
    if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2709
        tlb_flush(env, 1);
2710

    
2711
    if (msr_ile) {
2712
        new_msr |= (target_ulong)1 << MSR_LE;
2713
    }
2714

    
2715
    /* Jump to handler */
2716
    vector = env->excp_vectors[excp];
2717
    if (vector == (target_ulong)-1ULL) {
2718
        cpu_abort(env, "Raised an exception without defined vector %d\n",
2719
                  excp);
2720
    }
2721
    vector |= env->excp_prefix;
2722
#if defined(TARGET_PPC64)
2723
    if (excp_model == POWERPC_EXCP_BOOKE) {
2724
        if (!msr_icm) {
2725
            vector = (uint32_t)vector;
2726
        } else {
2727
            new_msr |= (target_ulong)1 << MSR_CM;
2728
        }
2729
    } else {
2730
        if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2731
            vector = (uint32_t)vector;
2732
        } else {
2733
            new_msr |= (target_ulong)1 << MSR_SF;
2734
        }
2735
    }
2736
#endif
2737
    /* XXX: we don't use hreg_store_msr here as already have treated
2738
     *      any special case that could occur. Just store MSR and update hflags
2739
     */
2740
    env->msr = new_msr & env->msr_mask;
2741
    hreg_compute_hflags(env);
2742
    env->nip = vector;
2743
    /* Reset exception state */
2744
    env->exception_index = POWERPC_EXCP_NONE;
2745
    env->error_code = 0;
2746

    
2747
    if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
2748
        (env->mmu_model == POWERPC_MMU_BOOKE206)) {
2749
        /* XXX: The BookE changes address space when switching modes,
2750
                we should probably implement that as different MMU indexes,
2751
                but for the moment we do it the slow way and flush all.  */
2752
        tlb_flush(env, 1);
2753
    }
2754
}
2755

    
2756
void do_interrupt (CPUState *env)
2757
{
2758
    powerpc_excp(env, env->excp_model, env->exception_index);
2759
}
2760

    
2761
void ppc_hw_interrupt (CPUPPCState *env)
2762
{
2763
    int hdice;
2764

    
2765
#if 0
2766
    qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
2767
                __func__, env, env->pending_interrupts,
2768
                env->interrupt_request, (int)msr_me, (int)msr_ee);
2769
#endif
2770
    /* External reset */
2771
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
2772
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
2773
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
2774
        return;
2775
    }
2776
    /* Machine check exception */
2777
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
2778
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
2779
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
2780
        return;
2781
    }
2782
#if 0 /* TODO */
2783
    /* External debug exception */
2784
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
2785
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2786
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
2787
        return;
2788
    }
2789
#endif
2790
    if (0) {
2791
        /* XXX: find a suitable condition to enable the hypervisor mode */
2792
        hdice = env->spr[SPR_LPCR] & 1;
2793
    } else {
2794
        hdice = 0;
2795
    }
2796
    if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
2797
        /* Hypervisor decrementer exception */
2798
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
2799
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
2800
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
2801
            return;
2802
        }
2803
    }
2804
    if (msr_ce != 0) {
2805
        /* External critical interrupt */
2806
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
2807
            /* Taking a critical external interrupt does not clear the external
2808
             * critical interrupt status
2809
             */
2810
#if 0
2811
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
2812
#endif
2813
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
2814
            return;
2815
        }
2816
    }
2817
    if (msr_ee != 0) {
2818
        /* Watchdog timer on embedded PowerPC */
2819
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
2820
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
2821
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
2822
            return;
2823
        }
2824
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
2825
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
2826
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
2827
            return;
2828
        }
2829
        /* Fixed interval timer on embedded PowerPC */
2830
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
2831
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
2832
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
2833
            return;
2834
        }
2835
        /* Programmable interval timer on embedded PowerPC */
2836
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
2837
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
2838
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
2839
            return;
2840
        }
2841
        /* Decrementer exception */
2842
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
2843
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
2844
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
2845
            return;
2846
        }
2847
        /* External interrupt */
2848
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
2849
            /* Taking an external interrupt does not clear the external
2850
             * interrupt status
2851
             */
2852
#if 0
2853
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
2854
#endif
2855
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
2856
            return;
2857
        }
2858
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
2859
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2860
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
2861
            return;
2862
        }
2863
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
2864
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
2865
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
2866
            return;
2867
        }
2868
        /* Thermal interrupt */
2869
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
2870
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
2871
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
2872
            return;
2873
        }
2874
    }
2875
}
2876
#endif /* !CONFIG_USER_ONLY */
2877

    
2878
void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2879
{
2880
    qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
2881
             TARGET_FMT_lx "\n", RA, msr);
2882
}
2883

    
2884
void cpu_reset(CPUPPCState *env)
2885
{
2886
    target_ulong msr;
2887

    
2888
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
2889
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
2890
        log_cpu_state(env, 0);
2891
    }
2892

    
2893
    msr = (target_ulong)0;
2894
    if (0) {
2895
        /* XXX: find a suitable condition to enable the hypervisor mode */
2896
        msr |= (target_ulong)MSR_HVB;
2897
    }
2898
    msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
2899
    msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
2900
    msr |= (target_ulong)1 << MSR_EP;
2901
#if defined (DO_SINGLE_STEP) && 0
2902
    /* Single step trace mode */
2903
    msr |= (target_ulong)1 << MSR_SE;
2904
    msr |= (target_ulong)1 << MSR_BE;
2905
#endif
2906
#if defined(CONFIG_USER_ONLY)
2907
    msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
2908
    msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
2909
    msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
2910
    msr |= (target_ulong)1 << MSR_PR;
2911
#else
2912
    env->excp_prefix = env->hreset_excp_prefix;
2913
    env->nip = env->hreset_vector | env->excp_prefix;
2914
    if (env->mmu_model != POWERPC_MMU_REAL)
2915
        ppc_tlb_invalidate_all(env);
2916
#endif
2917
    env->msr = msr & env->msr_mask;
2918
#if defined(TARGET_PPC64)
2919
    if (env->mmu_model & POWERPC_MMU_64)
2920
        env->msr |= (1ULL << MSR_SF);
2921
#endif
2922
    hreg_compute_hflags(env);
2923
    env->reserve_addr = (target_ulong)-1ULL;
2924
    /* Be sure no exception or interrupt is pending */
2925
    env->pending_interrupts = 0;
2926
    env->exception_index = POWERPC_EXCP_NONE;
2927
    env->error_code = 0;
2928
    /* Flush all TLBs */
2929
    tlb_flush(env, 1);
2930
}
2931

    
2932
CPUPPCState *cpu_ppc_init (const char *cpu_model)
2933
{
2934
    CPUPPCState *env;
2935
    const ppc_def_t *def;
2936

    
2937
    def = cpu_ppc_find_by_name(cpu_model);
2938
    if (!def)
2939
        return NULL;
2940

    
2941
    env = qemu_mallocz(sizeof(CPUPPCState));
2942
    cpu_exec_init(env);
2943
    ppc_translate_init();
2944
    env->cpu_model_str = cpu_model;
2945
    cpu_ppc_register_internal(env, def);
2946

    
2947
    qemu_init_vcpu(env);
2948

    
2949
    return env;
2950
}
2951

    
2952
void cpu_ppc_close (CPUPPCState *env)
2953
{
2954
    /* Should also remove all opcode tables... */
2955
    qemu_free(env);
2956
}