Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ fda6a0ec

History | View | Annotate | Download (91 kB)

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

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

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

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

    
48

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

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

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

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

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

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

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

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

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

    
101
    return 1;
102
}
103

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

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

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

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

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

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

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

    
172
    return access;
173
}
174

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

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

    
196
    return ret;
197
}
198

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

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

    
257
    return ret;
258
}
259

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

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

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

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

    
296
    return store;
297
}
298

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

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

    
313
    return nr;
314
}
315

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

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

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

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

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

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

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

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

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

    
441
    return ret;
442
}
443

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

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

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

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

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

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

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

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

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

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

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

    
661
    return ret;
662
}
663

    
664
static inline int find_pte32(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
665
                             int type, int target_page_bits)
666
{
667
    return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
668
}
669

    
670
#if defined(TARGET_PPC64)
671
static inline int find_pte64(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
672
                             int type, int target_page_bits)
673
{
674
    return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
675
}
676
#endif
677

    
678
static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
679
                           int type, int target_page_bits)
680
{
681
#if defined(TARGET_PPC64)
682
    if (env->mmu_model & POWERPC_MMU_64)
683
        return find_pte64(env, ctx, h, rw, type, target_page_bits);
684
#endif
685

    
686
    return find_pte32(env, ctx, h, rw, type, target_page_bits);
687
}
688

    
689
#if defined(TARGET_PPC64)
690
static inline ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
691
{
692
    uint64_t esid;
693
    int n;
694

    
695
    LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
696

    
697
    esid = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
698

    
699
    for (n = 0; n < env->slb_nr; n++) {
700
        ppc_slb_t *slb = &env->slb[n];
701

    
702
        LOG_SLB("%s: slot %d %016" PRIx64 " %016"
703
                    PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
704
        if (slb->esid == esid) {
705
            return slb;
706
        }
707
    }
708

    
709
    return NULL;
710
}
711

    
712
void ppc_slb_invalidate_all (CPUPPCState *env)
713
{
714
    int n, do_invalidate;
715

    
716
    do_invalidate = 0;
717
    /* XXX: Warning: slbia never invalidates the first segment */
718
    for (n = 1; n < env->slb_nr; n++) {
719
        ppc_slb_t *slb = &env->slb[n];
720

    
721
        if (slb->esid & SLB_ESID_V) {
722
            slb->esid &= ~SLB_ESID_V;
723
            /* XXX: given the fact that segment size is 256 MB or 1TB,
724
             *      and we still don't have a tlb_flush_mask(env, n, mask)
725
             *      in Qemu, we just invalidate all TLBs
726
             */
727
            do_invalidate = 1;
728
        }
729
    }
730
    if (do_invalidate)
731
        tlb_flush(env, 1);
732
}
733

    
734
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
735
{
736
    ppc_slb_t *slb;
737

    
738
    slb = slb_lookup(env, T0);
739
    if (!slb) {
740
        return;
741
    }
742

    
743
    if (slb->esid & SLB_ESID_V) {
744
        slb->esid &= ~SLB_ESID_V;
745

    
746
        /* XXX: given the fact that segment size is 256 MB or 1TB,
747
         *      and we still don't have a tlb_flush_mask(env, n, mask)
748
         *      in Qemu, we just invalidate all TLBs
749
         */
750
        tlb_flush(env, 1);
751
    }
752
}
753

    
754
int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
755
{
756
    int slot = rb & 0xfff;
757
    uint64_t esid = rb & ~0xfff;
758
    ppc_slb_t *slb = &env->slb[slot];
759

    
760
    if (slot >= env->slb_nr) {
761
        return -1;
762
    }
763

    
764
    slb->esid = esid;
765
    slb->vsid = rs;
766

    
767
    LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
768
            " %016" PRIx64 "\n", __func__, slot, rb, rs,
769
            slb->esid, slb->vsid);
770

    
771
    return 0;
772
}
773

    
774
int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
775
{
776
    int slot = rb & 0xfff;
777
    ppc_slb_t *slb = &env->slb[slot];
778

    
779
    if (slot >= env->slb_nr) {
780
        return -1;
781
    }
782

    
783
    *rt = slb->esid;
784
    return 0;
785
}
786

    
787
int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
788
{
789
    int slot = rb & 0xfff;
790
    ppc_slb_t *slb = &env->slb[slot];
791

    
792
    if (slot >= env->slb_nr) {
793
        return -1;
794
    }
795

    
796
    *rt = slb->vsid;
797
    return 0;
798
}
799
#endif /* defined(TARGET_PPC64) */
800

    
801
/* Perform segment based translation */
802
static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
803
                              target_ulong eaddr, int rw, int type)
804
{
805
    target_phys_addr_t hash;
806
    target_ulong sr, vsid, pgidx, page_mask;
807
    int ds, pr, target_page_bits;
808
    int ret, ret2;
809

    
810
    pr = msr_pr;
811
#if defined(TARGET_PPC64)
812
    if (env->mmu_model & POWERPC_MMU_64) {
813
        ppc_slb_t *slb;
814

    
815
        LOG_MMU("Check SLBs\n");
816
        slb = slb_lookup(env, eaddr);
817
        if (!slb) {
818
            return -5;
819
        }
820

    
821
        vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
822
        page_mask = ~SEGMENT_MASK_256M;
823
        target_page_bits = (slb->vsid & SLB_VSID_L)
824
            ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
825
        ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
826
                      : (slb->vsid & SLB_VSID_KS));
827
        ds = 0;
828
        ctx->nx = !!(slb->vsid & SLB_VSID_N);
829
        ctx->eaddr = eaddr;
830
    } else
831
#endif /* defined(TARGET_PPC64) */
832
    {
833
        sr = env->sr[eaddr >> 28];
834
        page_mask = 0x0FFFFFFF;
835
        ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
836
                    ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
837
        ds = sr & 0x80000000 ? 1 : 0;
838
        ctx->nx = sr & 0x10000000 ? 1 : 0;
839
        vsid = sr & 0x00FFFFFF;
840
        target_page_bits = TARGET_PAGE_BITS;
841
        LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
842
                TARGET_FMT_lx " lr=" TARGET_FMT_lx
843
                " ir=%d dr=%d pr=%d %d t=%d\n",
844
                eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
845
                (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
846
    }
847
    LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
848
            ctx->key, ds, ctx->nx, vsid);
849
    ret = -1;
850
    if (!ds) {
851
        /* Check if instruction fetch is allowed, if needed */
852
        if (type != ACCESS_CODE || ctx->nx == 0) {
853
            /* Page address translation */
854
            pgidx = (eaddr & page_mask) >> target_page_bits;
855
#if defined(TARGET_PPC64)
856
            if (env->mmu_model & POWERPC_MMU_64) {
857
                /* XXX: this is false for 1 TB segments */
858
                hash = vsid ^ pgidx;
859
            } else
860
#endif
861
            {
862
                hash = vsid ^ pgidx;
863
            }
864
            LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
865
                    " hash " TARGET_FMT_plx "\n",
866
                    env->htab_base, env->htab_mask, hash);
867
            ctx->hash[0] = hash;
868
            ctx->hash[1] = ~hash;
869

    
870
#if defined(TARGET_PPC64)
871
            if (env->mmu_model & POWERPC_MMU_64) {
872
                /* Only 5 bits of the page index are used in the AVPN */
873
                if (target_page_bits > 23) {
874
                    ctx->ptem = (vsid << 12) |
875
                                ((pgidx << (target_page_bits - 16)) & 0xF80);
876
                } else {
877
                    ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
878
                }
879
            } else
880
#endif
881
            {
882
                ctx->ptem = (vsid << 7) | (pgidx >> 10);
883
            }
884
            /* Initialize real address with an invalid value */
885
            ctx->raddr = (target_phys_addr_t)-1ULL;
886
            if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
887
                         env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
888
                /* Software TLB search */
889
                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
890
            } else {
891
                LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
892
                        " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
893
                        " hash=" TARGET_FMT_plx "\n",
894
                        env->htab_base, env->htab_mask, vsid, pgidx,
895
                        ctx->hash[0]);
896
                /* Primary table lookup */
897
                ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
898
                if (ret < 0) {
899
                    /* Secondary table lookup */
900
                    if (eaddr != 0xEFFFFFFF)
901
                        LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
902
                                " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
903
                                " hash=" TARGET_FMT_plx " pg_addr="
904
                                TARGET_FMT_plx "\n", env->htab_base,
905
                                env->htab_mask, vsid, pgidx, hash,
906
                                ctx->hash[1]);
907
                    ret2 = find_pte(env, ctx, 1, rw, type,
908
                                    target_page_bits);
909
                    if (ret2 != -1)
910
                        ret = ret2;
911
                }
912
            }
913
#if defined (DUMP_PAGE_TABLES)
914
            if (qemu_log_enabled()) {
915
                target_phys_addr_t curaddr;
916
                uint32_t a0, a1, a2, a3;
917
                qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
918
                         "\n", sdr, mask + 0x80);
919
                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
920
                     curaddr += 16) {
921
                    a0 = ldl_phys(curaddr);
922
                    a1 = ldl_phys(curaddr + 4);
923
                    a2 = ldl_phys(curaddr + 8);
924
                    a3 = ldl_phys(curaddr + 12);
925
                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
926
                        qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
927
                                 curaddr, a0, a1, a2, a3);
928
                    }
929
                }
930
            }
931
#endif
932
        } else {
933
            LOG_MMU("No access allowed\n");
934
            ret = -3;
935
        }
936
    } else {
937
        LOG_MMU("direct store...\n");
938
        /* Direct-store segment : absolutely *BUGGY* for now */
939
        switch (type) {
940
        case ACCESS_INT:
941
            /* Integer load/store : only access allowed */
942
            break;
943
        case ACCESS_CODE:
944
            /* No code fetch is allowed in direct-store areas */
945
            return -4;
946
        case ACCESS_FLOAT:
947
            /* Floating point load/store */
948
            return -4;
949
        case ACCESS_RES:
950
            /* lwarx, ldarx or srwcx. */
951
            return -4;
952
        case ACCESS_CACHE:
953
            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
954
            /* Should make the instruction do no-op.
955
             * As it already do no-op, it's quite easy :-)
956
             */
957
            ctx->raddr = eaddr;
958
            return 0;
959
        case ACCESS_EXT:
960
            /* eciwx or ecowx */
961
            return -4;
962
        default:
963
            qemu_log("ERROR: instruction should not need "
964
                        "address translation\n");
965
            return -4;
966
        }
967
        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
968
            ctx->raddr = eaddr;
969
            ret = 2;
970
        } else {
971
            ret = -2;
972
        }
973
    }
974

    
975
    return ret;
976
}
977

    
978
/* Generic TLB check function for embedded PowerPC implementations */
979
static inline int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
980
                                   target_phys_addr_t *raddrp,
981
                                   target_ulong address, uint32_t pid, int ext,
982
                                   int i)
983
{
984
    target_ulong mask;
985

    
986
    /* Check valid flag */
987
    if (!(tlb->prot & PAGE_VALID)) {
988
        return -1;
989
    }
990
    mask = ~(tlb->size - 1);
991
    LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
992
              " " TARGET_FMT_lx " %u\n", __func__, i, address, pid, tlb->EPN,
993
              mask, (uint32_t)tlb->PID);
994
    /* Check PID */
995
    if (tlb->PID != 0 && tlb->PID != pid)
996
        return -1;
997
    /* Check effective address */
998
    if ((address & mask) != tlb->EPN)
999
        return -1;
1000
    *raddrp = (tlb->RPN & mask) | (address & ~mask);
1001
#if (TARGET_PHYS_ADDR_BITS >= 36)
1002
    if (ext) {
1003
        /* Extend the physical address to 36 bits */
1004
        *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1005
    }
1006
#endif
1007

    
1008
    return 0;
1009
}
1010

    
1011
/* Generic TLB search function for PowerPC embedded implementations */
1012
int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1013
{
1014
    ppcemb_tlb_t *tlb;
1015
    target_phys_addr_t raddr;
1016
    int i, ret;
1017

    
1018
    /* Default return value is no match */
1019
    ret = -1;
1020
    for (i = 0; i < env->nb_tlb; i++) {
1021
        tlb = &env->tlb[i].tlbe;
1022
        if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1023
            ret = i;
1024
            break;
1025
        }
1026
    }
1027

    
1028
    return ret;
1029
}
1030

    
1031
/* Helpers specific to PowerPC 40x implementations */
1032
static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
1033
{
1034
    ppcemb_tlb_t *tlb;
1035
    int i;
1036

    
1037
    for (i = 0; i < env->nb_tlb; i++) {
1038
        tlb = &env->tlb[i].tlbe;
1039
        tlb->prot &= ~PAGE_VALID;
1040
    }
1041
    tlb_flush(env, 1);
1042
}
1043

    
1044
static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
1045
                                              target_ulong eaddr, uint32_t pid)
1046
{
1047
#if !defined(FLUSH_ALL_TLBS)
1048
    ppcemb_tlb_t *tlb;
1049
    target_phys_addr_t raddr;
1050
    target_ulong page, end;
1051
    int i;
1052

    
1053
    for (i = 0; i < env->nb_tlb; i++) {
1054
        tlb = &env->tlb[i].tlbe;
1055
        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1056
            end = tlb->EPN + tlb->size;
1057
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1058
                tlb_flush_page(env, page);
1059
            tlb->prot &= ~PAGE_VALID;
1060
            break;
1061
        }
1062
    }
1063
#else
1064
    ppc4xx_tlb_invalidate_all(env);
1065
#endif
1066
}
1067

    
1068
static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1069
                                 target_ulong address, int rw, int access_type)
1070
{
1071
    ppcemb_tlb_t *tlb;
1072
    target_phys_addr_t raddr;
1073
    int i, ret, zsel, zpr, pr;
1074

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

    
1127
    return ret;
1128
}
1129

    
1130
void store_40x_sler (CPUPPCState *env, uint32_t val)
1131
{
1132
    /* XXX: TO BE FIXED */
1133
    if (val != 0x00000000) {
1134
        cpu_abort(env, "Little-endian regions are not supported by now\n");
1135
    }
1136
    env->spr[SPR_405_SLER] = val;
1137
}
1138

    
1139
static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1140
                                          target_ulong address, int rw,
1141
                                          int access_type)
1142
{
1143
    ppcemb_tlb_t *tlb;
1144
    target_phys_addr_t raddr;
1145
    int i, prot, ret;
1146

    
1147
    ret = -1;
1148
    raddr = (target_phys_addr_t)-1ULL;
1149
    for (i = 0; i < env->nb_tlb; i++) {
1150
        tlb = &env->tlb[i].tlbe;
1151
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1152
                             env->spr[SPR_BOOKE_PID], 1, i) < 0)
1153
            continue;
1154
        if (msr_pr != 0)
1155
            prot = tlb->prot & 0xF;
1156
        else
1157
            prot = (tlb->prot >> 4) & 0xF;
1158
        /* Check the address space */
1159
        if (access_type == ACCESS_CODE) {
1160
            if (msr_ir != (tlb->attr & 1))
1161
                continue;
1162
            ctx->prot = prot;
1163
            if (prot & PAGE_EXEC) {
1164
                ret = 0;
1165
                break;
1166
            }
1167
            ret = -3;
1168
        } else {
1169
            if (msr_dr != (tlb->attr & 1))
1170
                continue;
1171
            ctx->prot = prot;
1172
            if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
1173
                ret = 0;
1174
                break;
1175
            }
1176
            ret = -2;
1177
        }
1178
    }
1179
    if (ret >= 0)
1180
        ctx->raddr = raddr;
1181

    
1182
    return ret;
1183
}
1184

    
1185
static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1186
                                 target_ulong eaddr, int rw)
1187
{
1188
    int in_plb, ret;
1189

    
1190
    ctx->raddr = eaddr;
1191
    ctx->prot = PAGE_READ | PAGE_EXEC;
1192
    ret = 0;
1193
    switch (env->mmu_model) {
1194
    case POWERPC_MMU_32B:
1195
    case POWERPC_MMU_601:
1196
    case POWERPC_MMU_SOFT_6xx:
1197
    case POWERPC_MMU_SOFT_74xx:
1198
    case POWERPC_MMU_SOFT_4xx:
1199
    case POWERPC_MMU_REAL:
1200
    case POWERPC_MMU_BOOKE:
1201
        ctx->prot |= PAGE_WRITE;
1202
        break;
1203
#if defined(TARGET_PPC64)
1204
    case POWERPC_MMU_620:
1205
    case POWERPC_MMU_64B:
1206
        /* Real address are 60 bits long */
1207
        ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1208
        ctx->prot |= PAGE_WRITE;
1209
        break;
1210
#endif
1211
    case POWERPC_MMU_SOFT_4xx_Z:
1212
        if (unlikely(msr_pe != 0)) {
1213
            /* 403 family add some particular protections,
1214
             * using PBL/PBU registers for accesses with no translation.
1215
             */
1216
            in_plb =
1217
                /* Check PLB validity */
1218
                (env->pb[0] < env->pb[1] &&
1219
                 /* and address in plb area */
1220
                 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1221
                (env->pb[2] < env->pb[3] &&
1222
                 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1223
            if (in_plb ^ msr_px) {
1224
                /* Access in protected area */
1225
                if (rw == 1) {
1226
                    /* Access is not allowed */
1227
                    ret = -2;
1228
                }
1229
            } else {
1230
                /* Read-write access is allowed */
1231
                ctx->prot |= PAGE_WRITE;
1232
            }
1233
        }
1234
        break;
1235
    case POWERPC_MMU_MPC8xx:
1236
        /* XXX: TODO */
1237
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1238
        break;
1239
    case POWERPC_MMU_BOOKE_FSL:
1240
        /* XXX: TODO */
1241
        cpu_abort(env, "BookE FSL MMU model not implemented\n");
1242
        break;
1243
    default:
1244
        cpu_abort(env, "Unknown or invalid MMU model\n");
1245
        return -1;
1246
    }
1247

    
1248
    return ret;
1249
}
1250

    
1251
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1252
                          int rw, int access_type)
1253
{
1254
    int ret;
1255

    
1256
#if 0
1257
    qemu_log("%s\n", __func__);
1258
#endif
1259
    if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1260
        (access_type != ACCESS_CODE && msr_dr == 0)) {
1261
        if (env->mmu_model == POWERPC_MMU_BOOKE) {
1262
            /* The BookE MMU always performs address translation. The
1263
               IS and DS bits only affect the address space.  */
1264
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1265
                                                rw, access_type);
1266
        } else {
1267
            /* No address translation.  */
1268
            ret = check_physical(env, ctx, eaddr, rw);
1269
        }
1270
    } else {
1271
        ret = -1;
1272
        switch (env->mmu_model) {
1273
        case POWERPC_MMU_32B:
1274
        case POWERPC_MMU_601:
1275
        case POWERPC_MMU_SOFT_6xx:
1276
        case POWERPC_MMU_SOFT_74xx:
1277
            /* Try to find a BAT */
1278
            if (env->nb_BATs != 0)
1279
                ret = get_bat(env, ctx, eaddr, rw, access_type);
1280
#if defined(TARGET_PPC64)
1281
        case POWERPC_MMU_620:
1282
        case POWERPC_MMU_64B:
1283
#endif
1284
            if (ret < 0) {
1285
                /* We didn't match any BAT entry or don't have BATs */
1286
                ret = get_segment(env, ctx, eaddr, rw, access_type);
1287
            }
1288
            break;
1289
        case POWERPC_MMU_SOFT_4xx:
1290
        case POWERPC_MMU_SOFT_4xx_Z:
1291
            ret = mmu40x_get_physical_address(env, ctx, eaddr,
1292
                                              rw, access_type);
1293
            break;
1294
        case POWERPC_MMU_BOOKE:
1295
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1296
                                                rw, access_type);
1297
            break;
1298
        case POWERPC_MMU_MPC8xx:
1299
            /* XXX: TODO */
1300
            cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1301
            break;
1302
        case POWERPC_MMU_BOOKE_FSL:
1303
            /* XXX: TODO */
1304
            cpu_abort(env, "BookE FSL MMU model not implemented\n");
1305
            return -1;
1306
        case POWERPC_MMU_REAL:
1307
            cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1308
            return -1;
1309
        default:
1310
            cpu_abort(env, "Unknown or invalid MMU model\n");
1311
            return -1;
1312
        }
1313
    }
1314
#if 0
1315
    qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1316
             __func__, eaddr, ret, ctx->raddr);
1317
#endif
1318

    
1319
    return ret;
1320
}
1321

    
1322
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1323
{
1324
    mmu_ctx_t ctx;
1325

    
1326
    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1327
        return -1;
1328

    
1329
    return ctx.raddr & TARGET_PAGE_MASK;
1330
}
1331

    
1332
/* Perform address translation */
1333
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1334
                              int mmu_idx, int is_softmmu)
1335
{
1336
    mmu_ctx_t ctx;
1337
    int access_type;
1338
    int ret = 0;
1339

    
1340
    if (rw == 2) {
1341
        /* code access */
1342
        rw = 0;
1343
        access_type = ACCESS_CODE;
1344
    } else {
1345
        /* data access */
1346
        access_type = env->access_type;
1347
    }
1348
    ret = get_physical_address(env, &ctx, address, rw, access_type);
1349
    if (ret == 0) {
1350
        tlb_set_page(env, address & TARGET_PAGE_MASK,
1351
                     ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1352
                     mmu_idx, TARGET_PAGE_SIZE);
1353
        ret = 0;
1354
    } else if (ret < 0) {
1355
        LOG_MMU_STATE(env);
1356
        if (access_type == ACCESS_CODE) {
1357
            switch (ret) {
1358
            case -1:
1359
                /* No matches in page tables or TLB */
1360
                switch (env->mmu_model) {
1361
                case POWERPC_MMU_SOFT_6xx:
1362
                    env->exception_index = POWERPC_EXCP_IFTLB;
1363
                    env->error_code = 1 << 18;
1364
                    env->spr[SPR_IMISS] = address;
1365
                    env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1366
                    goto tlb_miss;
1367
                case POWERPC_MMU_SOFT_74xx:
1368
                    env->exception_index = POWERPC_EXCP_IFTLB;
1369
                    goto tlb_miss_74xx;
1370
                case POWERPC_MMU_SOFT_4xx:
1371
                case POWERPC_MMU_SOFT_4xx_Z:
1372
                    env->exception_index = POWERPC_EXCP_ITLB;
1373
                    env->error_code = 0;
1374
                    env->spr[SPR_40x_DEAR] = address;
1375
                    env->spr[SPR_40x_ESR] = 0x00000000;
1376
                    break;
1377
                case POWERPC_MMU_32B:
1378
                case POWERPC_MMU_601:
1379
#if defined(TARGET_PPC64)
1380
                case POWERPC_MMU_620:
1381
                case POWERPC_MMU_64B:
1382
#endif
1383
                    env->exception_index = POWERPC_EXCP_ISI;
1384
                    env->error_code = 0x40000000;
1385
                    break;
1386
                case POWERPC_MMU_BOOKE:
1387
                    env->exception_index = POWERPC_EXCP_ITLB;
1388
                    env->error_code = 0;
1389
                    env->spr[SPR_BOOKE_DEAR] = address;
1390
                    return -1;
1391
                case POWERPC_MMU_BOOKE_FSL:
1392
                    /* XXX: TODO */
1393
                    cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1394
                    return -1;
1395
                case POWERPC_MMU_MPC8xx:
1396
                    /* XXX: TODO */
1397
                    cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1398
                    break;
1399
                case POWERPC_MMU_REAL:
1400
                    cpu_abort(env, "PowerPC in real mode should never raise "
1401
                              "any MMU exceptions\n");
1402
                    return -1;
1403
                default:
1404
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1405
                    return -1;
1406
                }
1407
                break;
1408
            case -2:
1409
                /* Access rights violation */
1410
                env->exception_index = POWERPC_EXCP_ISI;
1411
                env->error_code = 0x08000000;
1412
                break;
1413
            case -3:
1414
                /* No execute protection violation */
1415
                if (env->mmu_model == POWERPC_MMU_BOOKE) {
1416
                    env->spr[SPR_BOOKE_ESR] = 0x00000000;
1417
                }
1418
                env->exception_index = POWERPC_EXCP_ISI;
1419
                env->error_code = 0x10000000;
1420
                break;
1421
            case -4:
1422
                /* Direct store exception */
1423
                /* No code fetch is allowed in direct-store areas */
1424
                env->exception_index = POWERPC_EXCP_ISI;
1425
                env->error_code = 0x10000000;
1426
                break;
1427
#if defined(TARGET_PPC64)
1428
            case -5:
1429
                /* No match in segment table */
1430
                if (env->mmu_model == POWERPC_MMU_620) {
1431
                    env->exception_index = POWERPC_EXCP_ISI;
1432
                    /* XXX: this might be incorrect */
1433
                    env->error_code = 0x40000000;
1434
                } else {
1435
                    env->exception_index = POWERPC_EXCP_ISEG;
1436
                    env->error_code = 0;
1437
                }
1438
                break;
1439
#endif
1440
            }
1441
        } else {
1442
            switch (ret) {
1443
            case -1:
1444
                /* No matches in page tables or TLB */
1445
                switch (env->mmu_model) {
1446
                case POWERPC_MMU_SOFT_6xx:
1447
                    if (rw == 1) {
1448
                        env->exception_index = POWERPC_EXCP_DSTLB;
1449
                        env->error_code = 1 << 16;
1450
                    } else {
1451
                        env->exception_index = POWERPC_EXCP_DLTLB;
1452
                        env->error_code = 0;
1453
                    }
1454
                    env->spr[SPR_DMISS] = address;
1455
                    env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1456
                tlb_miss:
1457
                    env->error_code |= ctx.key << 19;
1458
                    env->spr[SPR_HASH1] = env->htab_base +
1459
                        get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1460
                    env->spr[SPR_HASH2] = env->htab_base +
1461
                        get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1462
                    break;
1463
                case POWERPC_MMU_SOFT_74xx:
1464
                    if (rw == 1) {
1465
                        env->exception_index = POWERPC_EXCP_DSTLB;
1466
                    } else {
1467
                        env->exception_index = POWERPC_EXCP_DLTLB;
1468
                    }
1469
                tlb_miss_74xx:
1470
                    /* Implement LRU algorithm */
1471
                    env->error_code = ctx.key << 19;
1472
                    env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1473
                        ((env->last_way + 1) & (env->nb_ways - 1));
1474
                    env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1475
                    break;
1476
                case POWERPC_MMU_SOFT_4xx:
1477
                case POWERPC_MMU_SOFT_4xx_Z:
1478
                    env->exception_index = POWERPC_EXCP_DTLB;
1479
                    env->error_code = 0;
1480
                    env->spr[SPR_40x_DEAR] = address;
1481
                    if (rw)
1482
                        env->spr[SPR_40x_ESR] = 0x00800000;
1483
                    else
1484
                        env->spr[SPR_40x_ESR] = 0x00000000;
1485
                    break;
1486
                case POWERPC_MMU_32B:
1487
                case POWERPC_MMU_601:
1488
#if defined(TARGET_PPC64)
1489
                case POWERPC_MMU_620:
1490
                case POWERPC_MMU_64B:
1491
#endif
1492
                    env->exception_index = POWERPC_EXCP_DSI;
1493
                    env->error_code = 0;
1494
                    env->spr[SPR_DAR] = address;
1495
                    if (rw == 1)
1496
                        env->spr[SPR_DSISR] = 0x42000000;
1497
                    else
1498
                        env->spr[SPR_DSISR] = 0x40000000;
1499
                    break;
1500
                case POWERPC_MMU_MPC8xx:
1501
                    /* XXX: TODO */
1502
                    cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1503
                    break;
1504
                case POWERPC_MMU_BOOKE:
1505
                    env->exception_index = POWERPC_EXCP_DTLB;
1506
                    env->error_code = 0;
1507
                    env->spr[SPR_BOOKE_DEAR] = address;
1508
                    env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1509
                    return -1;
1510
                case POWERPC_MMU_BOOKE_FSL:
1511
                    /* XXX: TODO */
1512
                    cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1513
                    return -1;
1514
                case POWERPC_MMU_REAL:
1515
                    cpu_abort(env, "PowerPC in real mode should never raise "
1516
                              "any MMU exceptions\n");
1517
                    return -1;
1518
                default:
1519
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1520
                    return -1;
1521
                }
1522
                break;
1523
            case -2:
1524
                /* Access rights violation */
1525
                env->exception_index = POWERPC_EXCP_DSI;
1526
                env->error_code = 0;
1527
                if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1528
                    || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1529
                    env->spr[SPR_40x_DEAR] = address;
1530
                    if (rw) {
1531
                        env->spr[SPR_40x_ESR] |= 0x00800000;
1532
                    }
1533
                } else if (env->mmu_model == POWERPC_MMU_BOOKE) {
1534
                    env->spr[SPR_BOOKE_DEAR] = address;
1535
                    env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1536
                } else {
1537
                    env->spr[SPR_DAR] = address;
1538
                    if (rw == 1) {
1539
                        env->spr[SPR_DSISR] = 0x0A000000;
1540
                    } else {
1541
                        env->spr[SPR_DSISR] = 0x08000000;
1542
                    }
1543
                }
1544
                break;
1545
            case -4:
1546
                /* Direct store exception */
1547
                switch (access_type) {
1548
                case ACCESS_FLOAT:
1549
                    /* Floating point load/store */
1550
                    env->exception_index = POWERPC_EXCP_ALIGN;
1551
                    env->error_code = POWERPC_EXCP_ALIGN_FP;
1552
                    env->spr[SPR_DAR] = address;
1553
                    break;
1554
                case ACCESS_RES:
1555
                    /* lwarx, ldarx or stwcx. */
1556
                    env->exception_index = POWERPC_EXCP_DSI;
1557
                    env->error_code = 0;
1558
                    env->spr[SPR_DAR] = address;
1559
                    if (rw == 1)
1560
                        env->spr[SPR_DSISR] = 0x06000000;
1561
                    else
1562
                        env->spr[SPR_DSISR] = 0x04000000;
1563
                    break;
1564
                case ACCESS_EXT:
1565
                    /* eciwx or ecowx */
1566
                    env->exception_index = POWERPC_EXCP_DSI;
1567
                    env->error_code = 0;
1568
                    env->spr[SPR_DAR] = address;
1569
                    if (rw == 1)
1570
                        env->spr[SPR_DSISR] = 0x06100000;
1571
                    else
1572
                        env->spr[SPR_DSISR] = 0x04100000;
1573
                    break;
1574
                default:
1575
                    printf("DSI: invalid exception (%d)\n", ret);
1576
                    env->exception_index = POWERPC_EXCP_PROGRAM;
1577
                    env->error_code =
1578
                        POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1579
                    env->spr[SPR_DAR] = address;
1580
                    break;
1581
                }
1582
                break;
1583
#if defined(TARGET_PPC64)
1584
            case -5:
1585
                /* No match in segment table */
1586
                if (env->mmu_model == POWERPC_MMU_620) {
1587
                    env->exception_index = POWERPC_EXCP_DSI;
1588
                    env->error_code = 0;
1589
                    env->spr[SPR_DAR] = address;
1590
                    /* XXX: this might be incorrect */
1591
                    if (rw == 1)
1592
                        env->spr[SPR_DSISR] = 0x42000000;
1593
                    else
1594
                        env->spr[SPR_DSISR] = 0x40000000;
1595
                } else {
1596
                    env->exception_index = POWERPC_EXCP_DSEG;
1597
                    env->error_code = 0;
1598
                    env->spr[SPR_DAR] = address;
1599
                }
1600
                break;
1601
#endif
1602
            }
1603
        }
1604
#if 0
1605
        printf("%s: set exception to %d %02x\n", __func__,
1606
               env->exception, env->error_code);
1607
#endif
1608
        ret = 1;
1609
    }
1610

    
1611
    return ret;
1612
}
1613

    
1614
/*****************************************************************************/
1615
/* BATs management */
1616
#if !defined(FLUSH_ALL_TLBS)
1617
static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1618
                                     target_ulong mask)
1619
{
1620
    target_ulong base, end, page;
1621

    
1622
    base = BATu & ~0x0001FFFF;
1623
    end = base + mask + 0x00020000;
1624
    LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1625
             TARGET_FMT_lx ")\n", base, end, mask);
1626
    for (page = base; page != end; page += TARGET_PAGE_SIZE)
1627
        tlb_flush_page(env, page);
1628
    LOG_BATS("Flush done\n");
1629
}
1630
#endif
1631

    
1632
static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1633
                                  target_ulong value)
1634
{
1635
    LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1636
             nr, ul == 0 ? 'u' : 'l', value, env->nip);
1637
}
1638

    
1639
void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1640
{
1641
    target_ulong mask;
1642

    
1643
    dump_store_bat(env, 'I', 0, nr, value);
1644
    if (env->IBAT[0][nr] != value) {
1645
        mask = (value << 15) & 0x0FFE0000UL;
1646
#if !defined(FLUSH_ALL_TLBS)
1647
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1648
#endif
1649
        /* When storing valid upper BAT, mask BEPI and BRPN
1650
         * and invalidate all TLBs covered by this BAT
1651
         */
1652
        mask = (value << 15) & 0x0FFE0000UL;
1653
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1654
            (value & ~0x0001FFFFUL & ~mask);
1655
        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1656
            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1657
#if !defined(FLUSH_ALL_TLBS)
1658
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1659
#else
1660
        tlb_flush(env, 1);
1661
#endif
1662
    }
1663
}
1664

    
1665
void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1666
{
1667
    dump_store_bat(env, 'I', 1, nr, value);
1668
    env->IBAT[1][nr] = value;
1669
}
1670

    
1671
void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1672
{
1673
    target_ulong mask;
1674

    
1675
    dump_store_bat(env, 'D', 0, nr, value);
1676
    if (env->DBAT[0][nr] != value) {
1677
        /* When storing valid upper BAT, mask BEPI and BRPN
1678
         * and invalidate all TLBs covered by this BAT
1679
         */
1680
        mask = (value << 15) & 0x0FFE0000UL;
1681
#if !defined(FLUSH_ALL_TLBS)
1682
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1683
#endif
1684
        mask = (value << 15) & 0x0FFE0000UL;
1685
        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1686
            (value & ~0x0001FFFFUL & ~mask);
1687
        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1688
            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1689
#if !defined(FLUSH_ALL_TLBS)
1690
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1691
#else
1692
        tlb_flush(env, 1);
1693
#endif
1694
    }
1695
}
1696

    
1697
void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1698
{
1699
    dump_store_bat(env, 'D', 1, nr, value);
1700
    env->DBAT[1][nr] = value;
1701
}
1702

    
1703
void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1704
{
1705
    target_ulong mask;
1706
#if defined(FLUSH_ALL_TLBS)
1707
    int do_inval;
1708
#endif
1709

    
1710
    dump_store_bat(env, 'I', 0, nr, value);
1711
    if (env->IBAT[0][nr] != value) {
1712
#if defined(FLUSH_ALL_TLBS)
1713
        do_inval = 0;
1714
#endif
1715
        mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1716
        if (env->IBAT[1][nr] & 0x40) {
1717
            /* Invalidate BAT only if it is valid */
1718
#if !defined(FLUSH_ALL_TLBS)
1719
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1720
#else
1721
            do_inval = 1;
1722
#endif
1723
        }
1724
        /* When storing valid upper BAT, mask BEPI and BRPN
1725
         * and invalidate all TLBs covered by this BAT
1726
         */
1727
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1728
            (value & ~0x0001FFFFUL & ~mask);
1729
        env->DBAT[0][nr] = env->IBAT[0][nr];
1730
        if (env->IBAT[1][nr] & 0x40) {
1731
#if !defined(FLUSH_ALL_TLBS)
1732
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1733
#else
1734
            do_inval = 1;
1735
#endif
1736
        }
1737
#if defined(FLUSH_ALL_TLBS)
1738
        if (do_inval)
1739
            tlb_flush(env, 1);
1740
#endif
1741
    }
1742
}
1743

    
1744
void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1745
{
1746
    target_ulong mask;
1747
#if defined(FLUSH_ALL_TLBS)
1748
    int do_inval;
1749
#endif
1750

    
1751
    dump_store_bat(env, 'I', 1, nr, value);
1752
    if (env->IBAT[1][nr] != value) {
1753
#if defined(FLUSH_ALL_TLBS)
1754
        do_inval = 0;
1755
#endif
1756
        if (env->IBAT[1][nr] & 0x40) {
1757
#if !defined(FLUSH_ALL_TLBS)
1758
            mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1759
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1760
#else
1761
            do_inval = 1;
1762
#endif
1763
        }
1764
        if (value & 0x40) {
1765
#if !defined(FLUSH_ALL_TLBS)
1766
            mask = (value << 17) & 0x0FFE0000UL;
1767
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1768
#else
1769
            do_inval = 1;
1770
#endif
1771
        }
1772
        env->IBAT[1][nr] = value;
1773
        env->DBAT[1][nr] = value;
1774
#if defined(FLUSH_ALL_TLBS)
1775
        if (do_inval)
1776
            tlb_flush(env, 1);
1777
#endif
1778
    }
1779
}
1780

    
1781
/*****************************************************************************/
1782
/* TLB management */
1783
void ppc_tlb_invalidate_all (CPUPPCState *env)
1784
{
1785
    switch (env->mmu_model) {
1786
    case POWERPC_MMU_SOFT_6xx:
1787
    case POWERPC_MMU_SOFT_74xx:
1788
        ppc6xx_tlb_invalidate_all(env);
1789
        break;
1790
    case POWERPC_MMU_SOFT_4xx:
1791
    case POWERPC_MMU_SOFT_4xx_Z:
1792
        ppc4xx_tlb_invalidate_all(env);
1793
        break;
1794
    case POWERPC_MMU_REAL:
1795
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1796
        break;
1797
    case POWERPC_MMU_MPC8xx:
1798
        /* XXX: TODO */
1799
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1800
        break;
1801
    case POWERPC_MMU_BOOKE:
1802
        tlb_flush(env, 1);
1803
        break;
1804
    case POWERPC_MMU_BOOKE_FSL:
1805
        /* XXX: TODO */
1806
        if (!kvm_enabled())
1807
            cpu_abort(env, "BookE MMU model is not implemented\n");
1808
        break;
1809
    case POWERPC_MMU_32B:
1810
    case POWERPC_MMU_601:
1811
#if defined(TARGET_PPC64)
1812
    case POWERPC_MMU_620:
1813
    case POWERPC_MMU_64B:
1814
#endif /* defined(TARGET_PPC64) */
1815
        tlb_flush(env, 1);
1816
        break;
1817
    default:
1818
        /* XXX: TODO */
1819
        cpu_abort(env, "Unknown MMU model\n");
1820
        break;
1821
    }
1822
}
1823

    
1824
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
1825
{
1826
#if !defined(FLUSH_ALL_TLBS)
1827
    addr &= TARGET_PAGE_MASK;
1828
    switch (env->mmu_model) {
1829
    case POWERPC_MMU_SOFT_6xx:
1830
    case POWERPC_MMU_SOFT_74xx:
1831
        ppc6xx_tlb_invalidate_virt(env, addr, 0);
1832
        if (env->id_tlbs == 1)
1833
            ppc6xx_tlb_invalidate_virt(env, addr, 1);
1834
        break;
1835
    case POWERPC_MMU_SOFT_4xx:
1836
    case POWERPC_MMU_SOFT_4xx_Z:
1837
        ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
1838
        break;
1839
    case POWERPC_MMU_REAL:
1840
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1841
        break;
1842
    case POWERPC_MMU_MPC8xx:
1843
        /* XXX: TODO */
1844
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1845
        break;
1846
    case POWERPC_MMU_BOOKE:
1847
        /* XXX: TODO */
1848
        cpu_abort(env, "BookE MMU model is not implemented\n");
1849
        break;
1850
    case POWERPC_MMU_BOOKE_FSL:
1851
        /* XXX: TODO */
1852
        cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1853
        break;
1854
    case POWERPC_MMU_32B:
1855
    case POWERPC_MMU_601:
1856
        /* tlbie invalidate TLBs for all segments */
1857
        addr &= ~((target_ulong)-1ULL << 28);
1858
        /* XXX: this case should be optimized,
1859
         * giving a mask to tlb_flush_page
1860
         */
1861
        tlb_flush_page(env, addr | (0x0 << 28));
1862
        tlb_flush_page(env, addr | (0x1 << 28));
1863
        tlb_flush_page(env, addr | (0x2 << 28));
1864
        tlb_flush_page(env, addr | (0x3 << 28));
1865
        tlb_flush_page(env, addr | (0x4 << 28));
1866
        tlb_flush_page(env, addr | (0x5 << 28));
1867
        tlb_flush_page(env, addr | (0x6 << 28));
1868
        tlb_flush_page(env, addr | (0x7 << 28));
1869
        tlb_flush_page(env, addr | (0x8 << 28));
1870
        tlb_flush_page(env, addr | (0x9 << 28));
1871
        tlb_flush_page(env, addr | (0xA << 28));
1872
        tlb_flush_page(env, addr | (0xB << 28));
1873
        tlb_flush_page(env, addr | (0xC << 28));
1874
        tlb_flush_page(env, addr | (0xD << 28));
1875
        tlb_flush_page(env, addr | (0xE << 28));
1876
        tlb_flush_page(env, addr | (0xF << 28));
1877
        break;
1878
#if defined(TARGET_PPC64)
1879
    case POWERPC_MMU_620:
1880
    case POWERPC_MMU_64B:
1881
        /* tlbie invalidate TLBs for all segments */
1882
        /* XXX: given the fact that there are too many segments to invalidate,
1883
         *      and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
1884
         *      we just invalidate all TLBs
1885
         */
1886
        tlb_flush(env, 1);
1887
        break;
1888
#endif /* defined(TARGET_PPC64) */
1889
    default:
1890
        /* XXX: TODO */
1891
        cpu_abort(env, "Unknown MMU model\n");
1892
        break;
1893
    }
1894
#else
1895
    ppc_tlb_invalidate_all(env);
1896
#endif
1897
}
1898

    
1899
/*****************************************************************************/
1900
/* Special registers manipulation */
1901
#if defined(TARGET_PPC64)
1902
void ppc_store_asr (CPUPPCState *env, target_ulong value)
1903
{
1904
    if (env->asr != value) {
1905
        env->asr = value;
1906
        tlb_flush(env, 1);
1907
    }
1908
}
1909
#endif
1910

    
1911
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
1912
{
1913
    LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
1914
    if (env->spr[SPR_SDR1] != value) {
1915
        env->spr[SPR_SDR1] = value;
1916
#if defined(TARGET_PPC64)
1917
        if (env->mmu_model & POWERPC_MMU_64) {
1918
            target_ulong htabsize = value & SDR_64_HTABSIZE;
1919

    
1920
            if (htabsize > 28) {
1921
                fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
1922
                        " stored in SDR1\n", htabsize);
1923
                htabsize = 28;
1924
            }
1925
            env->htab_mask = (1ULL << (htabsize + 18)) - 1;
1926
            env->htab_base = value & SDR_64_HTABORG;
1927
        } else
1928
#endif /* defined(TARGET_PPC64) */
1929
        {
1930
            /* FIXME: Should check for valid HTABMASK values */
1931
            env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
1932
            env->htab_base = value & SDR_32_HTABORG;
1933
        }
1934
        tlb_flush(env, 1);
1935
    }
1936
}
1937

    
1938
#if defined(TARGET_PPC64)
1939
target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
1940
{
1941
    // XXX
1942
    return 0;
1943
}
1944
#endif
1945

    
1946
void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1947
{
1948
    LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
1949
            srnum, value, env->sr[srnum]);
1950
#if defined(TARGET_PPC64)
1951
    if (env->mmu_model & POWERPC_MMU_64) {
1952
        uint64_t rb = 0, rs = 0;
1953

    
1954
        /* ESID = srnum */
1955
        rb |= ((uint32_t)srnum & 0xf) << 28;
1956
        /* Set the valid bit */
1957
        rb |= 1 << 27;
1958
        /* Index = ESID */
1959
        rb |= (uint32_t)srnum;
1960

    
1961
        /* VSID = VSID */
1962
        rs |= (value & 0xfffffff) << 12;
1963
        /* flags = flags */
1964
        rs |= ((value >> 27) & 0xf) << 9;
1965

    
1966
        ppc_store_slb(env, rb, rs);
1967
    } else
1968
#endif
1969
    if (env->sr[srnum] != value) {
1970
        env->sr[srnum] = value;
1971
/* Invalidating 256MB of virtual memory in 4kB pages is way longer than
1972
   flusing the whole TLB. */
1973
#if !defined(FLUSH_ALL_TLBS) && 0
1974
        {
1975
            target_ulong page, end;
1976
            /* Invalidate 256 MB of virtual memory */
1977
            page = (16 << 20) * srnum;
1978
            end = page + (16 << 20);
1979
            for (; page != end; page += TARGET_PAGE_SIZE)
1980
                tlb_flush_page(env, page);
1981
        }
1982
#else
1983
        tlb_flush(env, 1);
1984
#endif
1985
    }
1986
}
1987
#endif /* !defined (CONFIG_USER_ONLY) */
1988

    
1989
/* GDBstub can read and write MSR... */
1990
void ppc_store_msr (CPUPPCState *env, target_ulong value)
1991
{
1992
    hreg_store_msr(env, value, 0);
1993
}
1994

    
1995
/*****************************************************************************/
1996
/* Exception processing */
1997
#if defined (CONFIG_USER_ONLY)
1998
void do_interrupt (CPUState *env)
1999
{
2000
    env->exception_index = POWERPC_EXCP_NONE;
2001
    env->error_code = 0;
2002
}
2003

    
2004
void ppc_hw_interrupt (CPUState *env)
2005
{
2006
    env->exception_index = POWERPC_EXCP_NONE;
2007
    env->error_code = 0;
2008
}
2009
#else /* defined (CONFIG_USER_ONLY) */
2010
static inline void dump_syscall(CPUState *env)
2011
{
2012
    qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2013
                  " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2014
                  " nip=" TARGET_FMT_lx "\n",
2015
                  ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2016
                  ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2017
                  ppc_dump_gpr(env, 6), env->nip);
2018
}
2019

    
2020
/* Note that this function should be greatly optimized
2021
 * when called with a constant excp, from ppc_hw_interrupt
2022
 */
2023
static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2024
{
2025
    target_ulong msr, new_msr, vector;
2026
    int srr0, srr1, asrr0, asrr1;
2027
    int lpes0, lpes1, lev;
2028

    
2029
    if (0) {
2030
        /* XXX: find a suitable condition to enable the hypervisor mode */
2031
        lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2032
        lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2033
    } else {
2034
        /* Those values ensure we won't enter the hypervisor mode */
2035
        lpes0 = 0;
2036
        lpes1 = 1;
2037
    }
2038

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

    
2042
    /* new srr1 value excluding must-be-zero bits */
2043
    msr = env->msr & ~0x783f0000ULL;
2044

    
2045
    /* new interrupt handler msr */
2046
    new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2047

    
2048
    /* target registers */
2049
    srr0 = SPR_SRR0;
2050
    srr1 = SPR_SRR1;
2051
    asrr0 = -1;
2052
    asrr1 = -1;
2053

    
2054
    switch (excp) {
2055
    case POWERPC_EXCP_NONE:
2056
        /* Should never happen */
2057
        return;
2058
    case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
2059
        switch (excp_model) {
2060
        case POWERPC_EXCP_40x:
2061
            srr0 = SPR_40x_SRR2;
2062
            srr1 = SPR_40x_SRR3;
2063
            break;
2064
        case POWERPC_EXCP_BOOKE:
2065
            srr0 = SPR_BOOKE_CSRR0;
2066
            srr1 = SPR_BOOKE_CSRR1;
2067
            break;
2068
        case POWERPC_EXCP_G2:
2069
            break;
2070
        default:
2071
            goto excp_invalid;
2072
        }
2073
        goto store_next;
2074
    case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
2075
        if (msr_me == 0) {
2076
            /* Machine check exception is not enabled.
2077
             * Enter checkstop state.
2078
             */
2079
            if (qemu_log_enabled()) {
2080
                qemu_log("Machine check while not allowed. "
2081
                        "Entering checkstop state\n");
2082
            } else {
2083
                fprintf(stderr, "Machine check while not allowed. "
2084
                        "Entering checkstop state\n");
2085
            }
2086
            env->halted = 1;
2087
            env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2088
        }
2089
        if (0) {
2090
            /* XXX: find a suitable condition to enable the hypervisor mode */
2091
            new_msr |= (target_ulong)MSR_HVB;
2092
        }
2093

    
2094
        /* machine check exceptions don't have ME set */
2095
        new_msr &= ~((target_ulong)1 << MSR_ME);
2096

    
2097
        /* XXX: should also have something loaded in DAR / DSISR */
2098
        switch (excp_model) {
2099
        case POWERPC_EXCP_40x:
2100
            srr0 = SPR_40x_SRR2;
2101
            srr1 = SPR_40x_SRR3;
2102
            break;
2103
        case POWERPC_EXCP_BOOKE:
2104
            srr0 = SPR_BOOKE_MCSRR0;
2105
            srr1 = SPR_BOOKE_MCSRR1;
2106
            asrr0 = SPR_BOOKE_CSRR0;
2107
            asrr1 = SPR_BOOKE_CSRR1;
2108
            break;
2109
        default:
2110
            break;
2111
        }
2112
        goto store_next;
2113
    case POWERPC_EXCP_DSI:       /* Data storage exception                   */
2114
        LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2115
                 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2116
        if (lpes1 == 0)
2117
            new_msr |= (target_ulong)MSR_HVB;
2118
        goto store_next;
2119
    case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
2120
        LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2121
                 "\n", msr, env->nip);
2122
        if (lpes1 == 0)
2123
            new_msr |= (target_ulong)MSR_HVB;
2124
        msr |= env->error_code;
2125
        goto store_next;
2126
    case POWERPC_EXCP_EXTERNAL:  /* External input                           */
2127
        if (lpes0 == 1)
2128
            new_msr |= (target_ulong)MSR_HVB;
2129
        goto store_next;
2130
    case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
2131
        if (lpes1 == 0)
2132
            new_msr |= (target_ulong)MSR_HVB;
2133
        /* XXX: this is false */
2134
        /* Get rS/rD and rA from faulting opcode */
2135
        env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2136
        goto store_current;
2137
    case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
2138
        switch (env->error_code & ~0xF) {
2139
        case POWERPC_EXCP_FP:
2140
            if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2141
                LOG_EXCP("Ignore floating point exception\n");
2142
                env->exception_index = POWERPC_EXCP_NONE;
2143
                env->error_code = 0;
2144
                return;
2145
            }
2146
            if (lpes1 == 0)
2147
                new_msr |= (target_ulong)MSR_HVB;
2148
            msr |= 0x00100000;
2149
            if (msr_fe0 == msr_fe1)
2150
                goto store_next;
2151
            msr |= 0x00010000;
2152
            break;
2153
        case POWERPC_EXCP_INVAL:
2154
            LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2155
            if (lpes1 == 0)
2156
                new_msr |= (target_ulong)MSR_HVB;
2157
            msr |= 0x00080000;
2158
            break;
2159
        case POWERPC_EXCP_PRIV:
2160
            if (lpes1 == 0)
2161
                new_msr |= (target_ulong)MSR_HVB;
2162
            msr |= 0x00040000;
2163
            break;
2164
        case POWERPC_EXCP_TRAP:
2165
            if (lpes1 == 0)
2166
                new_msr |= (target_ulong)MSR_HVB;
2167
            msr |= 0x00020000;
2168
            break;
2169
        default:
2170
            /* Should never occur */
2171
            cpu_abort(env, "Invalid program exception %d. Aborting\n",
2172
                      env->error_code);
2173
            break;
2174
        }
2175
        goto store_current;
2176
    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
2177
        if (lpes1 == 0)
2178
            new_msr |= (target_ulong)MSR_HVB;
2179
        goto store_current;
2180
    case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
2181
        dump_syscall(env);
2182
        lev = env->error_code;
2183
        if ((lev == 1) && cpu_ppc_hypercall) {
2184
            cpu_ppc_hypercall(env);
2185
            return;
2186
        }
2187
        if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2188
            new_msr |= (target_ulong)MSR_HVB;
2189
        goto store_next;
2190
    case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
2191
        goto store_current;
2192
    case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
2193
        if (lpes1 == 0)
2194
            new_msr |= (target_ulong)MSR_HVB;
2195
        goto store_next;
2196
    case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
2197
        /* FIT on 4xx */
2198
        LOG_EXCP("FIT exception\n");
2199
        goto store_next;
2200
    case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
2201
        LOG_EXCP("WDT exception\n");
2202
        switch (excp_model) {
2203
        case POWERPC_EXCP_BOOKE:
2204
            srr0 = SPR_BOOKE_CSRR0;
2205
            srr1 = SPR_BOOKE_CSRR1;
2206
            break;
2207
        default:
2208
            break;
2209
        }
2210
        goto store_next;
2211
    case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
2212
        goto store_next;
2213
    case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
2214
        goto store_next;
2215
    case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
2216
        switch (excp_model) {
2217
        case POWERPC_EXCP_BOOKE:
2218
            srr0 = SPR_BOOKE_DSRR0;
2219
            srr1 = SPR_BOOKE_DSRR1;
2220
            asrr0 = SPR_BOOKE_CSRR0;
2221
            asrr1 = SPR_BOOKE_CSRR1;
2222
            break;
2223
        default:
2224
            break;
2225
        }
2226
        /* XXX: TODO */
2227
        cpu_abort(env, "Debug exception is not implemented yet !\n");
2228
        goto store_next;
2229
    case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
2230
        goto store_current;
2231
    case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
2232
        /* XXX: TODO */
2233
        cpu_abort(env, "Embedded floating point data exception "
2234
                  "is not implemented yet !\n");
2235
        goto store_next;
2236
    case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
2237
        /* XXX: TODO */
2238
        cpu_abort(env, "Embedded floating point round exception "
2239
                  "is not implemented yet !\n");
2240
        goto store_next;
2241
    case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
2242
        /* XXX: TODO */
2243
        cpu_abort(env,
2244
                  "Performance counter exception is not implemented yet !\n");
2245
        goto store_next;
2246
    case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
2247
        /* XXX: TODO */
2248
        cpu_abort(env,
2249
                  "Embedded doorbell interrupt is not implemented yet !\n");
2250
        goto store_next;
2251
    case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
2252
        switch (excp_model) {
2253
        case POWERPC_EXCP_BOOKE:
2254
            srr0 = SPR_BOOKE_CSRR0;
2255
            srr1 = SPR_BOOKE_CSRR1;
2256
            break;
2257
        default:
2258
            break;
2259
        }
2260
        /* XXX: TODO */
2261
        cpu_abort(env, "Embedded doorbell critical interrupt "
2262
                  "is not implemented yet !\n");
2263
        goto store_next;
2264
    case POWERPC_EXCP_RESET:     /* System reset exception                   */
2265
        if (msr_pow) {
2266
            /* indicate that we resumed from power save mode */
2267
            msr |= 0x10000;
2268
        } else {
2269
            new_msr &= ~((target_ulong)1 << MSR_ME);
2270
        }
2271

    
2272
        if (0) {
2273
            /* XXX: find a suitable condition to enable the hypervisor mode */
2274
            new_msr |= (target_ulong)MSR_HVB;
2275
        }
2276
        goto store_next;
2277
    case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
2278
        if (lpes1 == 0)
2279
            new_msr |= (target_ulong)MSR_HVB;
2280
        goto store_next;
2281
    case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
2282
        if (lpes1 == 0)
2283
            new_msr |= (target_ulong)MSR_HVB;
2284
        goto store_next;
2285
    case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
2286
        srr0 = SPR_HSRR0;
2287
        srr1 = SPR_HSRR1;
2288
        new_msr |= (target_ulong)MSR_HVB;
2289
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2290
        goto store_next;
2291
    case POWERPC_EXCP_TRACE:     /* Trace exception                          */
2292
        if (lpes1 == 0)
2293
            new_msr |= (target_ulong)MSR_HVB;
2294
        goto store_next;
2295
    case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
2296
        srr0 = SPR_HSRR0;
2297
        srr1 = SPR_HSRR1;
2298
        new_msr |= (target_ulong)MSR_HVB;
2299
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2300
        goto store_next;
2301
    case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
2302
        srr0 = SPR_HSRR0;
2303
        srr1 = SPR_HSRR1;
2304
        new_msr |= (target_ulong)MSR_HVB;
2305
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2306
        goto store_next;
2307
    case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
2308
        srr0 = SPR_HSRR0;
2309
        srr1 = SPR_HSRR1;
2310
        new_msr |= (target_ulong)MSR_HVB;
2311
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2312
        goto store_next;
2313
    case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
2314
        srr0 = SPR_HSRR0;
2315
        srr1 = SPR_HSRR1;
2316
        new_msr |= (target_ulong)MSR_HVB;
2317
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2318
        goto store_next;
2319
    case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
2320
        if (lpes1 == 0)
2321
            new_msr |= (target_ulong)MSR_HVB;
2322
        goto store_current;
2323
    case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
2324
        LOG_EXCP("PIT exception\n");
2325
        goto store_next;
2326
    case POWERPC_EXCP_IO:        /* IO error exception                       */
2327
        /* XXX: TODO */
2328
        cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2329
        goto store_next;
2330
    case POWERPC_EXCP_RUNM:      /* Run mode exception                       */
2331
        /* XXX: TODO */
2332
        cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2333
        goto store_next;
2334
    case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 */
2335
        /* XXX: TODO */
2336
        cpu_abort(env, "602 emulation trap exception "
2337
                  "is not implemented yet !\n");
2338
        goto store_next;
2339
    case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
2340
        if (lpes1 == 0) /* XXX: check this */
2341
            new_msr |= (target_ulong)MSR_HVB;
2342
        switch (excp_model) {
2343
        case POWERPC_EXCP_602:
2344
        case POWERPC_EXCP_603:
2345
        case POWERPC_EXCP_603E:
2346
        case POWERPC_EXCP_G2:
2347
            goto tlb_miss_tgpr;
2348
        case POWERPC_EXCP_7x5:
2349
            goto tlb_miss;
2350
        case POWERPC_EXCP_74xx:
2351
            goto tlb_miss_74xx;
2352
        default:
2353
            cpu_abort(env, "Invalid instruction TLB miss exception\n");
2354
            break;
2355
        }
2356
        break;
2357
    case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
2358
        if (lpes1 == 0) /* XXX: check this */
2359
            new_msr |= (target_ulong)MSR_HVB;
2360
        switch (excp_model) {
2361
        case POWERPC_EXCP_602:
2362
        case POWERPC_EXCP_603:
2363
        case POWERPC_EXCP_603E:
2364
        case POWERPC_EXCP_G2:
2365
            goto tlb_miss_tgpr;
2366
        case POWERPC_EXCP_7x5:
2367
            goto tlb_miss;
2368
        case POWERPC_EXCP_74xx:
2369
            goto tlb_miss_74xx;
2370
        default:
2371
            cpu_abort(env, "Invalid data load TLB miss exception\n");
2372
            break;
2373
        }
2374
        break;
2375
    case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
2376
        if (lpes1 == 0) /* XXX: check this */
2377
            new_msr |= (target_ulong)MSR_HVB;
2378
        switch (excp_model) {
2379
        case POWERPC_EXCP_602:
2380
        case POWERPC_EXCP_603:
2381
        case POWERPC_EXCP_603E:
2382
        case POWERPC_EXCP_G2:
2383
        tlb_miss_tgpr:
2384
            /* Swap temporary saved registers with GPRs */
2385
            if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2386
                new_msr |= (target_ulong)1 << MSR_TGPR;
2387
                hreg_swap_gpr_tgpr(env);
2388
            }
2389
            goto tlb_miss;
2390
        case POWERPC_EXCP_7x5:
2391
        tlb_miss:
2392
#if defined (DEBUG_SOFTWARE_TLB)
2393
            if (qemu_log_enabled()) {
2394
                const char *es;
2395
                target_ulong *miss, *cmp;
2396
                int en;
2397
                if (excp == POWERPC_EXCP_IFTLB) {
2398
                    es = "I";
2399
                    en = 'I';
2400
                    miss = &env->spr[SPR_IMISS];
2401
                    cmp = &env->spr[SPR_ICMP];
2402
                } else {
2403
                    if (excp == POWERPC_EXCP_DLTLB)
2404
                        es = "DL";
2405
                    else
2406
                        es = "DS";
2407
                    en = 'D';
2408
                    miss = &env->spr[SPR_DMISS];
2409
                    cmp = &env->spr[SPR_DCMP];
2410
                }
2411
                qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2412
                         TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2413
                         TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2414
                         env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2415
                         env->error_code);
2416
            }
2417
#endif
2418
            msr |= env->crf[0] << 28;
2419
            msr |= env->error_code; /* key, D/I, S/L bits */
2420
            /* Set way using a LRU mechanism */
2421
            msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2422
            break;
2423
        case POWERPC_EXCP_74xx:
2424
        tlb_miss_74xx:
2425
#if defined (DEBUG_SOFTWARE_TLB)
2426
            if (qemu_log_enabled()) {
2427
                const char *es;
2428
                target_ulong *miss, *cmp;
2429
                int en;
2430
                if (excp == POWERPC_EXCP_IFTLB) {
2431
                    es = "I";
2432
                    en = 'I';
2433
                    miss = &env->spr[SPR_TLBMISS];
2434
                    cmp = &env->spr[SPR_PTEHI];
2435
                } else {
2436
                    if (excp == POWERPC_EXCP_DLTLB)
2437
                        es = "DL";
2438
                    else
2439
                        es = "DS";
2440
                    en = 'D';
2441
                    miss = &env->spr[SPR_TLBMISS];
2442
                    cmp = &env->spr[SPR_PTEHI];
2443
                }
2444
                qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2445
                         TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2446
                         env->error_code);
2447
            }
2448
#endif
2449
            msr |= env->error_code; /* key bit */
2450
            break;
2451
        default:
2452
            cpu_abort(env, "Invalid data store TLB miss exception\n");
2453
            break;
2454
        }
2455
        goto store_next;
2456
    case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
2457
        /* XXX: TODO */
2458
        cpu_abort(env, "Floating point assist exception "
2459
                  "is not implemented yet !\n");
2460
        goto store_next;
2461
    case POWERPC_EXCP_DABR:      /* Data address breakpoint                  */
2462
        /* XXX: TODO */
2463
        cpu_abort(env, "DABR exception is not implemented yet !\n");
2464
        goto store_next;
2465
    case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
2466
        /* XXX: TODO */
2467
        cpu_abort(env, "IABR exception is not implemented yet !\n");
2468
        goto store_next;
2469
    case POWERPC_EXCP_SMI:       /* System management interrupt              */
2470
        /* XXX: TODO */
2471
        cpu_abort(env, "SMI exception is not implemented yet !\n");
2472
        goto store_next;
2473
    case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
2474
        /* XXX: TODO */
2475
        cpu_abort(env, "Thermal management exception "
2476
                  "is not implemented yet !\n");
2477
        goto store_next;
2478
    case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
2479
        if (lpes1 == 0)
2480
            new_msr |= (target_ulong)MSR_HVB;
2481
        /* XXX: TODO */
2482
        cpu_abort(env,
2483
                  "Performance counter exception is not implemented yet !\n");
2484
        goto store_next;
2485
    case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
2486
        /* XXX: TODO */
2487
        cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2488
        goto store_next;
2489
    case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
2490
        /* XXX: TODO */
2491
        cpu_abort(env,
2492
                  "970 soft-patch exception is not implemented yet !\n");
2493
        goto store_next;
2494
    case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
2495
        /* XXX: TODO */
2496
        cpu_abort(env,
2497
                  "970 maintenance exception is not implemented yet !\n");
2498
        goto store_next;
2499
    case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             */
2500
        /* XXX: TODO */
2501
        cpu_abort(env, "Maskable external exception "
2502
                  "is not implemented yet !\n");
2503
        goto store_next;
2504
    case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         */
2505
        /* XXX: TODO */
2506
        cpu_abort(env, "Non maskable external exception "
2507
                  "is not implemented yet !\n");
2508
        goto store_next;
2509
    default:
2510
    excp_invalid:
2511
        cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2512
        break;
2513
    store_current:
2514
        /* save current instruction location */
2515
        env->spr[srr0] = env->nip - 4;
2516
        break;
2517
    store_next:
2518
        /* save next instruction location */
2519
        env->spr[srr0] = env->nip;
2520
        break;
2521
    }
2522
    /* Save MSR */
2523
    env->spr[srr1] = msr;
2524
    /* If any alternate SRR register are defined, duplicate saved values */
2525
    if (asrr0 != -1)
2526
        env->spr[asrr0] = env->spr[srr0];
2527
    if (asrr1 != -1)
2528
        env->spr[asrr1] = env->spr[srr1];
2529
    /* If we disactivated any translation, flush TLBs */
2530
    if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2531
        tlb_flush(env, 1);
2532

    
2533
    if (msr_ile) {
2534
        new_msr |= (target_ulong)1 << MSR_LE;
2535
    }
2536

    
2537
    /* Jump to handler */
2538
    vector = env->excp_vectors[excp];
2539
    if (vector == (target_ulong)-1ULL) {
2540
        cpu_abort(env, "Raised an exception without defined vector %d\n",
2541
                  excp);
2542
    }
2543
    vector |= env->excp_prefix;
2544
#if defined(TARGET_PPC64)
2545
    if (excp_model == POWERPC_EXCP_BOOKE) {
2546
        if (!msr_icm) {
2547
            vector = (uint32_t)vector;
2548
        } else {
2549
            new_msr |= (target_ulong)1 << MSR_CM;
2550
        }
2551
    } else {
2552
        if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2553
            vector = (uint32_t)vector;
2554
        } else {
2555
            new_msr |= (target_ulong)1 << MSR_SF;
2556
        }
2557
    }
2558
#endif
2559
    /* XXX: we don't use hreg_store_msr here as already have treated
2560
     *      any special case that could occur. Just store MSR and update hflags
2561
     */
2562
    env->msr = new_msr & env->msr_mask;
2563
    hreg_compute_hflags(env);
2564
    env->nip = vector;
2565
    /* Reset exception state */
2566
    env->exception_index = POWERPC_EXCP_NONE;
2567
    env->error_code = 0;
2568

    
2569
    if (env->mmu_model == POWERPC_MMU_BOOKE) {
2570
        /* XXX: The BookE changes address space when switching modes,
2571
                we should probably implement that as different MMU indexes,
2572
                but for the moment we do it the slow way and flush all.  */
2573
        tlb_flush(env, 1);
2574
    }
2575
}
2576

    
2577
void do_interrupt (CPUState *env)
2578
{
2579
    powerpc_excp(env, env->excp_model, env->exception_index);
2580
}
2581

    
2582
void ppc_hw_interrupt (CPUPPCState *env)
2583
{
2584
    int hdice;
2585

    
2586
#if 0
2587
    qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
2588
                __func__, env, env->pending_interrupts,
2589
                env->interrupt_request, (int)msr_me, (int)msr_ee);
2590
#endif
2591
    /* External reset */
2592
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
2593
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
2594
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
2595
        return;
2596
    }
2597
    /* Machine check exception */
2598
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
2599
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
2600
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
2601
        return;
2602
    }
2603
#if 0 /* TODO */
2604
    /* External debug exception */
2605
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
2606
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2607
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
2608
        return;
2609
    }
2610
#endif
2611
    if (0) {
2612
        /* XXX: find a suitable condition to enable the hypervisor mode */
2613
        hdice = env->spr[SPR_LPCR] & 1;
2614
    } else {
2615
        hdice = 0;
2616
    }
2617
    if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
2618
        /* Hypervisor decrementer exception */
2619
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
2620
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
2621
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
2622
            return;
2623
        }
2624
    }
2625
    if (msr_ce != 0) {
2626
        /* External critical interrupt */
2627
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
2628
            /* Taking a critical external interrupt does not clear the external
2629
             * critical interrupt status
2630
             */
2631
#if 0
2632
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
2633
#endif
2634
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
2635
            return;
2636
        }
2637
    }
2638
    if (msr_ee != 0) {
2639
        /* Watchdog timer on embedded PowerPC */
2640
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
2641
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
2642
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
2643
            return;
2644
        }
2645
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
2646
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
2647
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
2648
            return;
2649
        }
2650
        /* Fixed interval timer on embedded PowerPC */
2651
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
2652
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
2653
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
2654
            return;
2655
        }
2656
        /* Programmable interval timer on embedded PowerPC */
2657
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
2658
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
2659
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
2660
            return;
2661
        }
2662
        /* Decrementer exception */
2663
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
2664
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
2665
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
2666
            return;
2667
        }
2668
        /* External interrupt */
2669
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
2670
            /* Taking an external interrupt does not clear the external
2671
             * interrupt status
2672
             */
2673
#if 0
2674
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
2675
#endif
2676
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
2677
            return;
2678
        }
2679
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
2680
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2681
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
2682
            return;
2683
        }
2684
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
2685
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
2686
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
2687
            return;
2688
        }
2689
        /* Thermal interrupt */
2690
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
2691
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
2692
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
2693
            return;
2694
        }
2695
    }
2696
}
2697
#endif /* !CONFIG_USER_ONLY */
2698

    
2699
void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2700
{
2701
    qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
2702
             TARGET_FMT_lx "\n", RA, msr);
2703
}
2704

    
2705
void cpu_reset(CPUPPCState *env)
2706
{
2707
    target_ulong msr;
2708

    
2709
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
2710
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
2711
        log_cpu_state(env, 0);
2712
    }
2713

    
2714
    msr = (target_ulong)0;
2715
    if (0) {
2716
        /* XXX: find a suitable condition to enable the hypervisor mode */
2717
        msr |= (target_ulong)MSR_HVB;
2718
    }
2719
    msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
2720
    msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
2721
    msr |= (target_ulong)1 << MSR_EP;
2722
#if defined (DO_SINGLE_STEP) && 0
2723
    /* Single step trace mode */
2724
    msr |= (target_ulong)1 << MSR_SE;
2725
    msr |= (target_ulong)1 << MSR_BE;
2726
#endif
2727
#if defined(CONFIG_USER_ONLY)
2728
    msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
2729
    msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
2730
    msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
2731
    msr |= (target_ulong)1 << MSR_PR;
2732
#else
2733
    env->excp_prefix = env->hreset_excp_prefix;
2734
    env->nip = env->hreset_vector | env->excp_prefix;
2735
    if (env->mmu_model != POWERPC_MMU_REAL)
2736
        ppc_tlb_invalidate_all(env);
2737
#endif
2738
    env->msr = msr & env->msr_mask;
2739
#if defined(TARGET_PPC64)
2740
    if (env->mmu_model & POWERPC_MMU_64)
2741
        env->msr |= (1ULL << MSR_SF);
2742
#endif
2743
    hreg_compute_hflags(env);
2744
    env->reserve_addr = (target_ulong)-1ULL;
2745
    /* Be sure no exception or interrupt is pending */
2746
    env->pending_interrupts = 0;
2747
    env->exception_index = POWERPC_EXCP_NONE;
2748
    env->error_code = 0;
2749
    /* Flush all TLBs */
2750
    tlb_flush(env, 1);
2751
}
2752

    
2753
CPUPPCState *cpu_ppc_init (const char *cpu_model)
2754
{
2755
    CPUPPCState *env;
2756
    const ppc_def_t *def;
2757

    
2758
    def = cpu_ppc_find_by_name(cpu_model);
2759
    if (!def)
2760
        return NULL;
2761

    
2762
    env = qemu_mallocz(sizeof(CPUPPCState));
2763
    cpu_exec_init(env);
2764
    ppc_translate_init();
2765
    env->cpu_model_str = cpu_model;
2766
    cpu_ppc_register_internal(env, def);
2767

    
2768
    qemu_init_vcpu(env);
2769

    
2770
    return env;
2771
}
2772

    
2773
void cpu_ppc_close (CPUPPCState *env)
2774
{
2775
    /* Should also remove all opcode tables... */
2776
    qemu_free(env);
2777
}