Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ 9bf0960a

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

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

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

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

    
47

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

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

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

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

    
72
/*****************************************************************************/
73
/* PowerPC Hypercall emulation */
74

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

    
77
/*****************************************************************************/
78
/* PowerPC MMU emulation */
79

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

    
86
    if (rw == 2) {
87
        exception = POWERPC_EXCP_ISI;
88
        error_code = 0x40000000;
89
    } else {
90
        exception = POWERPC_EXCP_DSI;
91
        error_code = 0x40000000;
92
        if (rw)
93
            error_code |= 0x02000000;
94
        env->spr[SPR_DAR] = address;
95
        env->spr[SPR_DSISR] = error_code;
96
    }
97
    env->exception_index = exception;
98
    env->error_code = error_code;
99

    
100
    return 1;
101
}
102

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

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

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

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

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

    
134
static inline int pp_check(int key, int pp, int nx)
135
{
136
    int access;
137

    
138
    /* Compute access rights */
139
    /* When pp is 3/7, the result is undefined. Set it to noaccess */
140
    access = 0;
141
    if (key == 0) {
142
        switch (pp) {
143
        case 0x0:
144
        case 0x1:
145
        case 0x2:
146
            access |= PAGE_WRITE;
147
            /* No break here */
148
        case 0x3:
149
        case 0x6:
150
            access |= PAGE_READ;
151
            break;
152
        }
153
    } else {
154
        switch (pp) {
155
        case 0x0:
156
        case 0x6:
157
            access = 0;
158
            break;
159
        case 0x1:
160
        case 0x3:
161
            access = PAGE_READ;
162
            break;
163
        case 0x2:
164
            access = PAGE_READ | PAGE_WRITE;
165
            break;
166
        }
167
    }
168
    if (nx == 0)
169
        access |= PAGE_EXEC;
170

    
171
    return access;
172
}
173

    
174
static inline int check_prot(int prot, int rw, int access_type)
175
{
176
    int ret;
177

    
178
    if (access_type == ACCESS_CODE) {
179
        if (prot & PAGE_EXEC)
180
            ret = 0;
181
        else
182
            ret = -2;
183
    } else if (rw) {
184
        if (prot & PAGE_WRITE)
185
            ret = 0;
186
        else
187
            ret = -2;
188
    } else {
189
        if (prot & PAGE_READ)
190
            ret = 0;
191
        else
192
            ret = -2;
193
    }
194

    
195
    return ret;
196
}
197

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

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

    
256
    return ret;
257
}
258

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

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

    
273
static inline int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
274
                                   int ret, int rw)
275
{
276
    int store = 0;
277

    
278
    /* Update page flags */
279
    if (!(*pte1p & 0x00000100)) {
280
        /* Update accessed flag */
281
        *pte1p |= 0x00000100;
282
        store = 1;
283
    }
284
    if (!(*pte1p & 0x00000080)) {
285
        if (rw == 1 && ret == 0) {
286
            /* Update changed flag */
287
            *pte1p |= 0x00000080;
288
            store = 1;
289
        } else {
290
            /* Force page fault for first write access */
291
            ctx->prot &= ~PAGE_WRITE;
292
        }
293
    }
294

    
295
    return store;
296
}
297

    
298
/* Software driven TLB helpers */
299
static inline int ppc6xx_tlb_getnum(CPUState *env, target_ulong eaddr, int way,
300
                                    int is_code)
301
{
302
    int nr;
303

    
304
    /* Select TLB num in a way from address */
305
    nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
306
    /* Select TLB way */
307
    nr += env->tlb_per_way * way;
308
    /* 6xx have separate TLBs for instructions and data */
309
    if (is_code && env->id_tlbs == 1)
310
        nr += env->nb_tlb;
311

    
312
    return nr;
313
}
314

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

    
320
    //LOG_SWTLB("Invalidate all TLBs\n");
321
    /* Invalidate all defined software TLB */
322
    max = env->nb_tlb;
323
    if (env->id_tlbs == 1)
324
        max *= 2;
325
    for (nr = 0; nr < max; nr++) {
326
        tlb = &env->tlb[nr].tlb6;
327
        pte_invalidate(&tlb->pte0);
328
    }
329
    tlb_flush(env, 1);
330
}
331

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

    
340
    /* Invalidate ITLB + DTLB, all ways */
341
    for (way = 0; way < env->nb_ways; way++) {
342
        nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
343
        tlb = &env->tlb[nr].tlb6;
344
        if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
345
            LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
346
                      env->nb_tlb, eaddr);
347
            pte_invalidate(&tlb->pte0);
348
            tlb_flush_page(env, tlb->EPN);
349
        }
350
    }
351
#else
352
    /* XXX: PowerPC specification say this is valid as well */
353
    ppc6xx_tlb_invalidate_all(env);
354
#endif
355
}
356

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

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

    
369
    nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
370
    tlb = &env->tlb[nr].tlb6;
371
    LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
372
              " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
373
    /* Invalidate any pending reference in Qemu for this virtual address */
374
    __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
375
    tlb->pte0 = pte0;
376
    tlb->pte1 = pte1;
377
    tlb->EPN = EPN;
378
    /* Store last way for LRU mechanism */
379
    env->last_way = way;
380
}
381

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

    
389
    best = -1;
390
    ret = -1; /* No TLB found */
391
    for (way = 0; way < env->nb_ways; way++) {
392
        nr = ppc6xx_tlb_getnum(env, eaddr, way,
393
                               access_type == ACCESS_CODE ? 1 : 0);
394
        tlb = &env->tlb[nr].tlb6;
395
        /* This test "emulates" the PTE index match for hardware TLBs */
396
        if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
397
            LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
398
                      "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb,
399
                      pte_is_valid(tlb->pte0) ? "valid" : "inval",
400
                      tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
401
            continue;
402
        }
403
        LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " "
404
                  TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb,
405
                  pte_is_valid(tlb->pte0) ? "valid" : "inval",
406
                  tlb->EPN, eaddr, tlb->pte1,
407
                  rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
408
        switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
409
        case -3:
410
            /* TLB inconsistency */
411
            return -1;
412
        case -2:
413
            /* Access violation */
414
            ret = -2;
415
            best = nr;
416
            break;
417
        case -1:
418
        default:
419
            /* No match */
420
            break;
421
        case 0:
422
            /* access granted */
423
            /* XXX: we should go on looping to check all TLBs consistency
424
             *      but we can speed-up the whole thing as the
425
             *      result would be undefined if TLBs are not consistent.
426
             */
427
            ret = 0;
428
            best = nr;
429
            goto done;
430
        }
431
    }
432
    if (best != -1) {
433
    done:
434
        LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
435
                  ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
436
        /* Update page flags */
437
        pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
438
    }
439

    
440
    return ret;
441
}
442

    
443
/* Perform BAT hit & translation */
444
static inline void bat_size_prot(CPUState *env, target_ulong *blp, int *validp,
445
                                 int *protp, target_ulong *BATu,
446
                                 target_ulong *BATl)
447
{
448
    target_ulong bl;
449
    int pp, valid, prot;
450

    
451
    bl = (*BATu & 0x00001FFC) << 15;
452
    valid = 0;
453
    prot = 0;
454
    if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
455
        ((msr_pr != 0) && (*BATu & 0x00000001))) {
456
        valid = 1;
457
        pp = *BATl & 0x00000003;
458
        if (pp != 0) {
459
            prot = PAGE_READ | PAGE_EXEC;
460
            if (pp == 0x2)
461
                prot |= PAGE_WRITE;
462
        }
463
    }
464
    *blp = bl;
465
    *validp = valid;
466
    *protp = prot;
467
}
468

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

    
476
    bl = (*BATl & 0x0000003F) << 17;
477
    LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
478
             (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
479
    prot = 0;
480
    valid = (*BATl >> 6) & 1;
481
    if (valid) {
482
        pp = *BATu & 0x00000003;
483
        if (msr_pr == 0)
484
            key = (*BATu >> 3) & 1;
485
        else
486
            key = (*BATu >> 2) & 1;
487
        prot = pp_check(key, pp, 0);
488
    }
489
    *blp = bl;
490
    *validp = valid;
491
    *protp = prot;
492
}
493

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

    
502
    LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
503
             type == ACCESS_CODE ? 'I' : 'D', virtual);
504
    switch (type) {
505
    case ACCESS_CODE:
506
        BATlt = env->IBAT[1];
507
        BATut = env->IBAT[0];
508
        break;
509
    default:
510
        BATlt = env->DBAT[1];
511
        BATut = env->DBAT[0];
512
        break;
513
    }
514
    for (i = 0; i < env->nb_BATs; i++) {
515
        BATu = &BATut[i];
516
        BATl = &BATlt[i];
517
        BEPIu = *BATu & 0xF0000000;
518
        BEPIl = *BATu & 0x0FFE0000;
519
        if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
520
            bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
521
        } else {
522
            bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
523
        }
524
        LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
525
                 " BATl " TARGET_FMT_lx "\n", __func__,
526
                 type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
527
        if ((virtual & 0xF0000000) == BEPIu &&
528
            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
529
            /* BAT matches */
530
            if (valid != 0) {
531
                /* Get physical address */
532
                ctx->raddr = (*BATl & 0xF0000000) |
533
                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
534
                    (virtual & 0x0001F000);
535
                /* Compute access rights */
536
                ctx->prot = prot;
537
                ret = check_prot(ctx->prot, rw, type);
538
                if (ret == 0)
539
                    LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
540
                             i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
541
                             ctx->prot & PAGE_WRITE ? 'W' : '-');
542
                break;
543
            }
544
        }
545
    }
546
    if (ret < 0) {
547
#if defined(DEBUG_BATS)
548
        if (qemu_log_enabled()) {
549
            LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
550
            for (i = 0; i < 4; i++) {
551
                BATu = &BATut[i];
552
                BATl = &BATlt[i];
553
                BEPIu = *BATu & 0xF0000000;
554
                BEPIl = *BATu & 0x0FFE0000;
555
                bl = (*BATu & 0x00001FFC) << 15;
556
                LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
557
                         " BATl " TARGET_FMT_lx " \n\t" TARGET_FMT_lx " "
558
                         TARGET_FMT_lx " " TARGET_FMT_lx "\n",
559
                         __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
560
                         *BATu, *BATl, BEPIu, BEPIl, bl);
561
            }
562
        }
563
#endif
564
    }
565
    /* No hit */
566
    return ret;
567
}
568

    
569
static inline target_phys_addr_t get_pteg_offset(CPUState *env,
570
                                                 target_phys_addr_t hash,
571
                                                 int pte_size)
572
{
573
    return (hash * pte_size * 8) & env->htab_mask;
574
}
575

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

    
585
    ret = -1; /* No entry found */
586
    pteg_off = get_pteg_offset(env, ctx->hash[h],
587
                               is_64b ? HASH_PTE_SIZE_64 : HASH_PTE_SIZE_32);
588
    for (i = 0; i < 8; i++) {
589
#if defined(TARGET_PPC64)
590
        if (is_64b) {
591
            if (env->external_htab) {
592
                pte0 = ldq_p(env->external_htab + pteg_off + (i * 16));
593
                pte1 = ldq_p(env->external_htab + pteg_off + (i * 16) + 8);
594
            } else {
595
                pte0 = ldq_phys(env->htab_base + pteg_off + (i * 16));
596
                pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
597
            }
598

    
599
            /* We have a TLB that saves 4K pages, so let's
600
             * split a huge page to 4k chunks */
601
            if (target_page_bits != TARGET_PAGE_BITS)
602
                pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1))
603
                        & TARGET_PAGE_MASK;
604

    
605
            r = pte64_check(ctx, pte0, pte1, h, rw, type);
606
            LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
607
                    TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
608
                    pteg_off + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
609
                    (int)((pte0 >> 1) & 1), ctx->ptem);
610
        } else
611
#endif
612
        {
613
            if (env->external_htab) {
614
                pte0 = ldl_p(env->external_htab + pteg_off + (i * 8));
615
                pte1 = ldl_p(env->external_htab + pteg_off + (i * 8) + 4);
616
            } else {
617
                pte0 = ldl_phys(env->htab_base + pteg_off + (i * 8));
618
                pte1 = ldl_phys(env->htab_base + pteg_off + (i * 8) + 4);
619
            }
620
            r = pte32_check(ctx, pte0, pte1, h, rw, type);
621
            LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
622
                    TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
623
                    pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
624
                    (int)((pte0 >> 6) & 1), ctx->ptem);
625
        }
626
        switch (r) {
627
        case -3:
628
            /* PTE inconsistency */
629
            return -1;
630
        case -2:
631
            /* Access violation */
632
            ret = -2;
633
            good = i;
634
            break;
635
        case -1:
636
        default:
637
            /* No PTE match */
638
            break;
639
        case 0:
640
            /* access granted */
641
            /* XXX: we should go on looping to check all PTEs consistency
642
             *      but if we can speed-up the whole thing as the
643
             *      result would be undefined if PTEs are not consistent.
644
             */
645
            ret = 0;
646
            good = i;
647
            goto done;
648
        }
649
    }
650
    if (good != -1) {
651
    done:
652
        LOG_MMU("found PTE at addr " TARGET_FMT_lx " prot=%01x ret=%d\n",
653
                ctx->raddr, ctx->prot, ret);
654
        /* Update page flags */
655
        pte1 = ctx->raddr;
656
        if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
657
#if defined(TARGET_PPC64)
658
            if (is_64b) {
659
                if (env->external_htab) {
660
                    stq_p(env->external_htab + pteg_off + (good * 16) + 8,
661
                          pte1);
662
                } else {
663
                    stq_phys_notdirty(env->htab_base + pteg_off +
664
                                      (good * 16) + 8, pte1);
665
                }
666
            } else
667
#endif
668
            {
669
                if (env->external_htab) {
670
                    stl_p(env->external_htab + pteg_off + (good * 8) + 4,
671
                          pte1);
672
                } else {
673
                    stl_phys_notdirty(env->htab_base + pteg_off +
674
                                      (good * 8) + 4, pte1);
675
                }
676
            }
677
        }
678
    }
679

    
680
    return ret;
681
}
682

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

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

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

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

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

    
705
    for (n = 0; n < env->slb_nr; n++) {
706
        ppc_slb_t *slb = &env->slb[n];
707

    
708
        LOG_SLB("%s: slot %d %016" PRIx64 " %016"
709
                    PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
710
        /* We check for 1T matches on all MMUs here - if the MMU
711
         * doesn't have 1T segment support, we will have prevented 1T
712
         * entries from being inserted in the slbmte code. */
713
        if (((slb->esid == esid_256M) &&
714
             ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_256M))
715
            || ((slb->esid == esid_1T) &&
716
                ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_1T))) {
717
            return slb;
718
        }
719
    }
720

    
721
    return NULL;
722
}
723

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

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

    
733
        if (slb->esid & SLB_ESID_V) {
734
            slb->esid &= ~SLB_ESID_V;
735
            /* XXX: given the fact that segment size is 256 MB or 1TB,
736
             *      and we still don't have a tlb_flush_mask(env, n, mask)
737
             *      in Qemu, we just invalidate all TLBs
738
             */
739
            do_invalidate = 1;
740
        }
741
    }
742
    if (do_invalidate)
743
        tlb_flush(env, 1);
744
}
745

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

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

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

    
758
        /* XXX: given the fact that segment size is 256 MB or 1TB,
759
         *      and we still don't have a tlb_flush_mask(env, n, mask)
760
         *      in Qemu, we just invalidate all TLBs
761
         */
762
        tlb_flush(env, 1);
763
    }
764
}
765

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

    
771
    if (rb & (0x1000 - env->slb_nr)) {
772
        return -1; /* Reserved bits set or slot too high */
773
    }
774
    if (rs & (SLB_VSID_B & ~SLB_VSID_B_1T)) {
775
        return -1; /* Bad segment size */
776
    }
777
    if ((rs & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG)) {
778
        return -1; /* 1T segment on MMU that doesn't support it */
779
    }
780

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

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

    
789
    return 0;
790
}
791

    
792
int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
793
{
794
    int slot = rb & 0xfff;
795
    ppc_slb_t *slb = &env->slb[slot];
796

    
797
    if (slot >= env->slb_nr) {
798
        return -1;
799
    }
800

    
801
    *rt = slb->esid;
802
    return 0;
803
}
804

    
805
int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
806
{
807
    int slot = rb & 0xfff;
808
    ppc_slb_t *slb = &env->slb[slot];
809

    
810
    if (slot >= env->slb_nr) {
811
        return -1;
812
    }
813

    
814
    *rt = slb->vsid;
815
    return 0;
816
}
817
#endif /* defined(TARGET_PPC64) */
818

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

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

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

    
842
        if (slb->vsid & SLB_VSID_B) {
843
            vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
844
            segment_bits = 40;
845
        } else {
846
            vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
847
            segment_bits = 28;
848
        }
849

    
850
        target_page_bits = (slb->vsid & SLB_VSID_L)
851
            ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
852
        ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
853
                      : (slb->vsid & SLB_VSID_KS));
854
        ds = 0;
855
        ctx->nx = !!(slb->vsid & SLB_VSID_N);
856

    
857
        pageaddr = eaddr & ((1ULL << segment_bits)
858
                            - (1ULL << target_page_bits));
859
        if (slb->vsid & SLB_VSID_B) {
860
            hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
861
        } else {
862
            hash = vsid ^ (pageaddr >> target_page_bits);
863
        }
864
        /* Only 5 bits of the page index are used in the AVPN */
865
        ctx->ptem = (slb->vsid & SLB_VSID_PTEM) |
866
            ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
867
    } else
868
#endif /* defined(TARGET_PPC64) */
869
    {
870
        target_ulong sr, pgidx;
871

    
872
        sr = env->sr[eaddr >> 28];
873
        ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
874
                    ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
875
        ds = sr & 0x80000000 ? 1 : 0;
876
        ctx->nx = sr & 0x10000000 ? 1 : 0;
877
        vsid = sr & 0x00FFFFFF;
878
        target_page_bits = TARGET_PAGE_BITS;
879
        LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
880
                TARGET_FMT_lx " lr=" TARGET_FMT_lx
881
                " ir=%d dr=%d pr=%d %d t=%d\n",
882
                eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
883
                (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
884
        pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
885
        hash = vsid ^ pgidx;
886
        ctx->ptem = (vsid << 7) | (pgidx >> 10);
887
    }
888
    LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
889
            ctx->key, ds, ctx->nx, vsid);
890
    ret = -1;
891
    if (!ds) {
892
        /* Check if instruction fetch is allowed, if needed */
893
        if (type != ACCESS_CODE || ctx->nx == 0) {
894
            /* Page address translation */
895
            LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
896
                    " hash " TARGET_FMT_plx "\n",
897
                    env->htab_base, env->htab_mask, hash);
898
            ctx->hash[0] = hash;
899
            ctx->hash[1] = ~hash;
900

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

    
990
    return ret;
991
}
992

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

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

    
1023
    return 0;
1024
}
1025

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

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

    
1043
    return ret;
1044
}
1045

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

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

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

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

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

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

    
1142
    return ret;
1143
}
1144

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

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

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

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

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

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

    
1182
found_tlb:
1183

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

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

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

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

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

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

    
1221
    return ret;
1222
}
1223

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

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

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

    
1253
    return ret;
1254
}
1255

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

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

    
1274
    tlb_flush(env, 1);
1275
}
1276

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

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

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

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

    
1301
found_tlb:
1302

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

    
1313
    return ret;
1314
}
1315

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

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

    
1379
    return ret;
1380
}
1381

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

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

    
1454
    return ret;
1455
}
1456

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

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

    
1464
    return ctx.raddr & TARGET_PAGE_MASK;
1465
}
1466

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

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

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

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

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

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

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

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

    
1788
    return ret;
1789
}
1790

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2946
    qemu_init_vcpu(env);
2947

    
2948
    return env;
2949
}
2950

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