Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (91.4 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_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
665
                           int type, int target_page_bits)
666
{
667
#if defined(TARGET_PPC64)
668
    if (env->mmu_model & POWERPC_MMU_64)
669
        return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
670
#endif
671

    
672
    return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
673
}
674

    
675
#if defined(TARGET_PPC64)
676
static inline ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
677
{
678
    uint64_t esid_256M, esid_1T;
679
    int n;
680

    
681
    LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
682

    
683
    esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
684
    esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V;
685

    
686
    for (n = 0; n < env->slb_nr; n++) {
687
        ppc_slb_t *slb = &env->slb[n];
688

    
689
        LOG_SLB("%s: slot %d %016" PRIx64 " %016"
690
                    PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
691
        /* We check for 1T matches on all MMUs here - if the MMU
692
         * doesn't have 1T segment support, we will have prevented 1T
693
         * entries from being inserted in the slbmte code. */
694
        if (((slb->esid == esid_256M) &&
695
             ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_256M))
696
            || ((slb->esid == esid_1T) &&
697
                ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_1T))) {
698
            return slb;
699
        }
700
    }
701

    
702
    return NULL;
703
}
704

    
705
void ppc_slb_invalidate_all (CPUPPCState *env)
706
{
707
    int n, do_invalidate;
708

    
709
    do_invalidate = 0;
710
    /* XXX: Warning: slbia never invalidates the first segment */
711
    for (n = 1; n < env->slb_nr; n++) {
712
        ppc_slb_t *slb = &env->slb[n];
713

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

    
727
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
728
{
729
    ppc_slb_t *slb;
730

    
731
    slb = slb_lookup(env, T0);
732
    if (!slb) {
733
        return;
734
    }
735

    
736
    if (slb->esid & SLB_ESID_V) {
737
        slb->esid &= ~SLB_ESID_V;
738

    
739
        /* XXX: given the fact that segment size is 256 MB or 1TB,
740
         *      and we still don't have a tlb_flush_mask(env, n, mask)
741
         *      in Qemu, we just invalidate all TLBs
742
         */
743
        tlb_flush(env, 1);
744
    }
745
}
746

    
747
int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
748
{
749
    int slot = rb & 0xfff;
750
    ppc_slb_t *slb = &env->slb[slot];
751

    
752
    if (rb & (0x1000 - env->slb_nr)) {
753
        return -1; /* Reserved bits set or slot too high */
754
    }
755
    if (rs & (SLB_VSID_B & ~SLB_VSID_B_1T)) {
756
        return -1; /* Bad segment size */
757
    }
758
    if ((rs & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG)) {
759
        return -1; /* 1T segment on MMU that doesn't support it */
760
    }
761

    
762
    /* Mask out the slot number as we store the entry */
763
    slb->esid = rb & (SLB_ESID_ESID | SLB_ESID_V);
764
    slb->vsid = rs;
765

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

    
770
    return 0;
771
}
772

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

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

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

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

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

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

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

    
809
    pr = msr_pr;
810
    ctx->eaddr = eaddr;
811
#if defined(TARGET_PPC64)
812
    if (env->mmu_model & POWERPC_MMU_64) {
813
        ppc_slb_t *slb;
814
        target_ulong pageaddr;
815
        int segment_bits;
816

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

    
823
        if (slb->vsid & SLB_VSID_B) {
824
            vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
825
            segment_bits = 40;
826
        } else {
827
            vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
828
            segment_bits = 28;
829
        }
830

    
831
        target_page_bits = (slb->vsid & SLB_VSID_L)
832
            ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
833
        ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
834
                      : (slb->vsid & SLB_VSID_KS));
835
        ds = 0;
836
        ctx->nx = !!(slb->vsid & SLB_VSID_N);
837

    
838
        pageaddr = eaddr & ((1ULL << segment_bits)
839
                            - (1ULL << target_page_bits));
840
        if (slb->vsid & SLB_VSID_B) {
841
            hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
842
        } else {
843
            hash = vsid ^ (pageaddr >> target_page_bits);
844
        }
845
        /* Only 5 bits of the page index are used in the AVPN */
846
        ctx->ptem = (slb->vsid & SLB_VSID_PTEM) |
847
            ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
848
    } else
849
#endif /* defined(TARGET_PPC64) */
850
    {
851
        target_ulong sr, pgidx;
852

    
853
        sr = env->sr[eaddr >> 28];
854
        ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
855
                    ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
856
        ds = sr & 0x80000000 ? 1 : 0;
857
        ctx->nx = sr & 0x10000000 ? 1 : 0;
858
        vsid = sr & 0x00FFFFFF;
859
        target_page_bits = TARGET_PAGE_BITS;
860
        LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
861
                TARGET_FMT_lx " lr=" TARGET_FMT_lx
862
                " ir=%d dr=%d pr=%d %d t=%d\n",
863
                eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
864
                (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
865
        pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
866
        hash = vsid ^ pgidx;
867
        ctx->ptem = (vsid << 7) | (pgidx >> 10);
868
    }
869
    LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
870
            ctx->key, ds, ctx->nx, vsid);
871
    ret = -1;
872
    if (!ds) {
873
        /* Check if instruction fetch is allowed, if needed */
874
        if (type != ACCESS_CODE || ctx->nx == 0) {
875
            /* Page address translation */
876
            LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
877
                    " hash " TARGET_FMT_plx "\n",
878
                    env->htab_base, env->htab_mask, hash);
879
            ctx->hash[0] = hash;
880
            ctx->hash[1] = ~hash;
881

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

    
972
    return ret;
973
}
974

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

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

    
1005
    return 0;
1006
}
1007

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

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

    
1025
    return ret;
1026
}
1027

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

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

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

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

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

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

    
1124
    return ret;
1125
}
1126

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

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

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

    
1179
    return ret;
1180
}
1181

    
1182
static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1183
                                 target_ulong eaddr, int rw)
1184
{
1185
    int in_plb, ret;
1186

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

    
1246
    return ret;
1247
}
1248

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

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

    
1318
    return ret;
1319
}
1320

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

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

    
1328
    return ctx.raddr & TARGET_PAGE_MASK;
1329
}
1330

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

    
1339
    if (rw == 2) {
1340
        /* code access */
1341
        rw = 0;
1342
        access_type = ACCESS_CODE;
1343
    } else {
1344
        /* data access */
1345
        access_type = env->access_type;
1346
    }
1347
    ret = get_physical_address(env, &ctx, address, rw, access_type);
1348
    if (ret == 0) {
1349
        tlb_set_page(env, address & TARGET_PAGE_MASK,
1350
                     ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1351
                     mmu_idx, TARGET_PAGE_SIZE);
1352
        ret = 0;
1353
    } else if (ret < 0) {
1354
        LOG_MMU_STATE(env);
1355
        if (access_type == ACCESS_CODE) {
1356
            switch (ret) {
1357
            case -1:
1358
                /* No matches in page tables or TLB */
1359
                switch (env->mmu_model) {
1360
                case POWERPC_MMU_SOFT_6xx:
1361
                    env->exception_index = POWERPC_EXCP_IFTLB;
1362
                    env->error_code = 1 << 18;
1363
                    env->spr[SPR_IMISS] = address;
1364
                    env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1365
                    goto tlb_miss;
1366
                case POWERPC_MMU_SOFT_74xx:
1367
                    env->exception_index = POWERPC_EXCP_IFTLB;
1368
                    goto tlb_miss_74xx;
1369
                case POWERPC_MMU_SOFT_4xx:
1370
                case POWERPC_MMU_SOFT_4xx_Z:
1371
                    env->exception_index = POWERPC_EXCP_ITLB;
1372
                    env->error_code = 0;
1373
                    env->spr[SPR_40x_DEAR] = address;
1374
                    env->spr[SPR_40x_ESR] = 0x00000000;
1375
                    break;
1376
                case POWERPC_MMU_32B:
1377
                case POWERPC_MMU_601:
1378
#if defined(TARGET_PPC64)
1379
                case POWERPC_MMU_620:
1380
                case POWERPC_MMU_64B:
1381
                case POWERPC_MMU_2_06:
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
                case POWERPC_MMU_2_06:
1492
#endif
1493
                    env->exception_index = POWERPC_EXCP_DSI;
1494
                    env->error_code = 0;
1495
                    env->spr[SPR_DAR] = address;
1496
                    if (rw == 1)
1497
                        env->spr[SPR_DSISR] = 0x42000000;
1498
                    else
1499
                        env->spr[SPR_DSISR] = 0x40000000;
1500
                    break;
1501
                case POWERPC_MMU_MPC8xx:
1502
                    /* XXX: TODO */
1503
                    cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1504
                    break;
1505
                case POWERPC_MMU_BOOKE:
1506
                    env->exception_index = POWERPC_EXCP_DTLB;
1507
                    env->error_code = 0;
1508
                    env->spr[SPR_BOOKE_DEAR] = address;
1509
                    env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1510
                    return -1;
1511
                case POWERPC_MMU_BOOKE_FSL:
1512
                    /* XXX: TODO */
1513
                    cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1514
                    return -1;
1515
                case POWERPC_MMU_REAL:
1516
                    cpu_abort(env, "PowerPC in real mode should never raise "
1517
                              "any MMU exceptions\n");
1518
                    return -1;
1519
                default:
1520
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1521
                    return -1;
1522
                }
1523
                break;
1524
            case -2:
1525
                /* Access rights violation */
1526
                env->exception_index = POWERPC_EXCP_DSI;
1527
                env->error_code = 0;
1528
                if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1529
                    || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1530
                    env->spr[SPR_40x_DEAR] = address;
1531
                    if (rw) {
1532
                        env->spr[SPR_40x_ESR] |= 0x00800000;
1533
                    }
1534
                } else if (env->mmu_model == POWERPC_MMU_BOOKE) {
1535
                    env->spr[SPR_BOOKE_DEAR] = address;
1536
                    env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1537
                } else {
1538
                    env->spr[SPR_DAR] = address;
1539
                    if (rw == 1) {
1540
                        env->spr[SPR_DSISR] = 0x0A000000;
1541
                    } else {
1542
                        env->spr[SPR_DSISR] = 0x08000000;
1543
                    }
1544
                }
1545
                break;
1546
            case -4:
1547
                /* Direct store exception */
1548
                switch (access_type) {
1549
                case ACCESS_FLOAT:
1550
                    /* Floating point load/store */
1551
                    env->exception_index = POWERPC_EXCP_ALIGN;
1552
                    env->error_code = POWERPC_EXCP_ALIGN_FP;
1553
                    env->spr[SPR_DAR] = address;
1554
                    break;
1555
                case ACCESS_RES:
1556
                    /* lwarx, ldarx or stwcx. */
1557
                    env->exception_index = POWERPC_EXCP_DSI;
1558
                    env->error_code = 0;
1559
                    env->spr[SPR_DAR] = address;
1560
                    if (rw == 1)
1561
                        env->spr[SPR_DSISR] = 0x06000000;
1562
                    else
1563
                        env->spr[SPR_DSISR] = 0x04000000;
1564
                    break;
1565
                case ACCESS_EXT:
1566
                    /* eciwx or ecowx */
1567
                    env->exception_index = POWERPC_EXCP_DSI;
1568
                    env->error_code = 0;
1569
                    env->spr[SPR_DAR] = address;
1570
                    if (rw == 1)
1571
                        env->spr[SPR_DSISR] = 0x06100000;
1572
                    else
1573
                        env->spr[SPR_DSISR] = 0x04100000;
1574
                    break;
1575
                default:
1576
                    printf("DSI: invalid exception (%d)\n", ret);
1577
                    env->exception_index = POWERPC_EXCP_PROGRAM;
1578
                    env->error_code =
1579
                        POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1580
                    env->spr[SPR_DAR] = address;
1581
                    break;
1582
                }
1583
                break;
1584
#if defined(TARGET_PPC64)
1585
            case -5:
1586
                /* No match in segment table */
1587
                if (env->mmu_model == POWERPC_MMU_620) {
1588
                    env->exception_index = POWERPC_EXCP_DSI;
1589
                    env->error_code = 0;
1590
                    env->spr[SPR_DAR] = address;
1591
                    /* XXX: this might be incorrect */
1592
                    if (rw == 1)
1593
                        env->spr[SPR_DSISR] = 0x42000000;
1594
                    else
1595
                        env->spr[SPR_DSISR] = 0x40000000;
1596
                } else {
1597
                    env->exception_index = POWERPC_EXCP_DSEG;
1598
                    env->error_code = 0;
1599
                    env->spr[SPR_DAR] = address;
1600
                }
1601
                break;
1602
#endif
1603
            }
1604
        }
1605
#if 0
1606
        printf("%s: set exception to %d %02x\n", __func__,
1607
               env->exception, env->error_code);
1608
#endif
1609
        ret = 1;
1610
    }
1611

    
1612
    return ret;
1613
}
1614

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1964
        /* VSID = VSID */
1965
        rs |= (value & 0xfffffff) << 12;
1966
        /* flags = flags */
1967
        rs |= ((value >> 27) & 0xf) << 9;
1968

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

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

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

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

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

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

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

    
2045
    /* new srr1 value excluding must-be-zero bits */
2046
    msr = env->msr & ~0x783f0000ULL;
2047

    
2048
    /* new interrupt handler msr */
2049
    new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2050

    
2051
    /* target registers */
2052
    srr0 = SPR_SRR0;
2053
    srr1 = SPR_SRR1;
2054
    asrr0 = -1;
2055
    asrr1 = -1;
2056

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

    
2097
        /* machine check exceptions don't have ME set */
2098
        new_msr &= ~((target_ulong)1 << MSR_ME);
2099

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

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

    
2536
    if (msr_ile) {
2537
        new_msr |= (target_ulong)1 << MSR_LE;
2538
    }
2539

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

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

    
2580
void do_interrupt (CPUState *env)
2581
{
2582
    powerpc_excp(env, env->excp_model, env->exception_index);
2583
}
2584

    
2585
void ppc_hw_interrupt (CPUPPCState *env)
2586
{
2587
    int hdice;
2588

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

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

    
2708
void cpu_reset(CPUPPCState *env)
2709
{
2710
    target_ulong msr;
2711

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

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

    
2756
CPUPPCState *cpu_ppc_init (const char *cpu_model)
2757
{
2758
    CPUPPCState *env;
2759
    const ppc_def_t *def;
2760

    
2761
    def = cpu_ppc_find_by_name(cpu_model);
2762
    if (!def)
2763
        return NULL;
2764

    
2765
    env = qemu_mallocz(sizeof(CPUPPCState));
2766
    cpu_exec_init(env);
2767
    ppc_translate_init();
2768
    env->cpu_model_str = cpu_model;
2769
    cpu_ppc_register_internal(env, def);
2770

    
2771
    qemu_init_vcpu(env);
2772

    
2773
    return env;
2774
}
2775

    
2776
void cpu_ppc_close (CPUPPCState *env)
2777
{
2778
    /* Should also remove all opcode tables... */
2779
    qemu_free(env);
2780
}