Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ efdef95f

History | View | Annotate | Download (91 kB)

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

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

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

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

    
48

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

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

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

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

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

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

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

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

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

    
101
    return 1;
102
}
103

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

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

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

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

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

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

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

    
172
    return access;
173
}
174

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

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

    
196
    return ret;
197
}
198

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

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

    
257
    return ret;
258
}
259

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

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

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

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

    
296
    return store;
297
}
298

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

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

    
313
    return nr;
314
}
315

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

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

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

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

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

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

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

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

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

    
441
    return ret;
442
}
443

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

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

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

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

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

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

    
570
/* PTE table lookup */
571
static inline int _find_pte(mmu_ctx_t *ctx, int is_64b, int h, int rw,
572
                            int type, int target_page_bits)
573
{
574
    target_ulong base, pte0, pte1;
575
    int i, good = -1;
576
    int ret, r;
577

    
578
    ret = -1; /* No entry found */
579
    base = ctx->pg_addr[h];
580
    for (i = 0; i < 8; i++) {
581
#if defined(TARGET_PPC64)
582
        if (is_64b) {
583
            pte0 = ldq_phys(base + (i * 16));
584
            pte1 = ldq_phys(base + (i * 16) + 8);
585

    
586
            /* We have a TLB that saves 4K pages, so let's
587
             * split a huge page to 4k chunks */
588
            if (target_page_bits != TARGET_PAGE_BITS)
589
                pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1))
590
                        & TARGET_PAGE_MASK;
591

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

    
650
    return ret;
651
}
652

    
653
static inline int find_pte32(mmu_ctx_t *ctx, int h, int rw, int type,
654
                             int target_page_bits)
655
{
656
    return _find_pte(ctx, 0, h, rw, type, target_page_bits);
657
}
658

    
659
#if defined(TARGET_PPC64)
660
static inline int find_pte64(mmu_ctx_t *ctx, int h, int rw, int type,
661
                             int target_page_bits)
662
{
663
    return _find_pte(ctx, 1, h, rw, type, target_page_bits);
664
}
665
#endif
666

    
667
static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
668
                           int type, int target_page_bits)
669
{
670
#if defined(TARGET_PPC64)
671
    if (env->mmu_model & POWERPC_MMU_64)
672
        return find_pte64(ctx, h, rw, type, target_page_bits);
673
#endif
674

    
675
    return find_pte32(ctx, h, rw, type, target_page_bits);
676
}
677

    
678
#if defined(TARGET_PPC64)
679
static inline int slb_lookup(CPUPPCState *env, target_ulong eaddr,
680
                             target_ulong *vsid, target_ulong *page_mask,
681
                             int *attr, int *target_page_bits)
682
{
683
    uint64_t esid;
684
    int n;
685

    
686
    LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
687

    
688
    esid = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
689

    
690
    for (n = 0; n < env->slb_nr; n++) {
691
        ppc_slb_t *slb = &env->slb[n];
692

    
693
        LOG_SLB("%s: slot %d %016" PRIx64 " %016"
694
                    PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
695
        if (slb->esid == esid) {
696
            *vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
697
            *page_mask = ~SEGMENT_MASK_256M;
698
            *attr = slb->vsid & SLB_VSID_ATTR;
699
            if (target_page_bits) {
700
                *target_page_bits = (slb->vsid & SLB_VSID_L)
701
                    ? TARGET_PAGE_BITS_16M
702
                    : TARGET_PAGE_BITS;
703
            }
704
            return n;
705
        }
706
    }
707

    
708
    return -5;
709
}
710

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

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

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

    
733
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
734
{
735
    target_ulong vsid, page_mask;
736
    int attr;
737
    int n;
738
    ppc_slb_t *slb;
739

    
740
    n = slb_lookup(env, T0, &vsid, &page_mask, &attr, NULL);
741
    if (n < 0) {
742
        return;
743
    }
744

    
745
    slb = &env->slb[n];
746

    
747
    if (slb->esid & SLB_ESID_V) {
748
        slb->esid &= ~SLB_ESID_V;
749

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

    
758
int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
759
{
760
    int slot = rb & 0xfff;
761
    uint64_t esid = rb & ~0xfff;
762
    ppc_slb_t *slb = &env->slb[slot];
763

    
764
    if (slot >= env->slb_nr) {
765
        return -1;
766
    }
767

    
768
    slb->esid = esid;
769
    slb->vsid = rs;
770

    
771
    LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
772
            " %016" PRIx64 "\n", __func__, slot, rb, rs,
773
            slb->esid, slb->vsid);
774

    
775
    return 0;
776
}
777

    
778
int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
779
{
780
    int slot = rb & 0xfff;
781
    ppc_slb_t *slb = &env->slb[slot];
782

    
783
    if (slot >= env->slb_nr) {
784
        return -1;
785
    }
786

    
787
    *rt = slb->esid;
788
    return 0;
789
}
790

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

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

    
800
    *rt = slb->vsid;
801
    return 0;
802
}
803
#endif /* defined(TARGET_PPC64) */
804

    
805
/* Perform segment based translation */
806
static inline target_phys_addr_t get_pgaddr(target_phys_addr_t sdr1,
807
                                            int sdr_sh,
808
                                            target_phys_addr_t hash,
809
                                            target_phys_addr_t mask)
810
{
811
    return (sdr1 & ((target_phys_addr_t)(-1ULL) << sdr_sh)) | (hash & mask);
812
}
813

    
814
static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
815
                              target_ulong eaddr, int rw, int type)
816
{
817
    target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
818
    target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
819
    int ds, vsid_sh, sdr_sh, pr, target_page_bits;
820
    int ret, ret2;
821

    
822
    pr = msr_pr;
823
#if defined(TARGET_PPC64)
824
    if (env->mmu_model & POWERPC_MMU_64) {
825
        int attr;
826

    
827
        LOG_MMU("Check SLBs\n");
828
        ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr,
829
                         &target_page_bits);
830
        if (ret < 0)
831
            return ret;
832
        ctx->key = !!(pr ? (attr & SLB_VSID_KP) : (attr & SLB_VSID_KS));
833
        ds = 0;
834
        ctx->nx = !!(attr & SLB_VSID_N);
835
        ctx->eaddr = eaddr;
836
        vsid_mask = 0x00003FFFFFFFFF80ULL;
837
        vsid_sh = 7;
838
        sdr_sh = 18;
839
        sdr_mask = 0x3FF80;
840
    } else
841
#endif /* defined(TARGET_PPC64) */
842
    {
843
        sr = env->sr[eaddr >> 28];
844
        page_mask = 0x0FFFFFFF;
845
        ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
846
                    ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
847
        ds = sr & 0x80000000 ? 1 : 0;
848
        ctx->nx = sr & 0x10000000 ? 1 : 0;
849
        vsid = sr & 0x00FFFFFF;
850
        vsid_mask = 0x01FFFFC0;
851
        vsid_sh = 6;
852
        sdr_sh = 16;
853
        sdr_mask = 0xFFC0;
854
        target_page_bits = TARGET_PAGE_BITS;
855
        LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
856
                TARGET_FMT_lx " lr=" TARGET_FMT_lx
857
                " ir=%d dr=%d pr=%d %d t=%d\n",
858
                eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
859
                (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
860
    }
861
    LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
862
            ctx->key, ds, ctx->nx, vsid);
863
    ret = -1;
864
    if (!ds) {
865
        /* Check if instruction fetch is allowed, if needed */
866
        if (type != ACCESS_CODE || ctx->nx == 0) {
867
            /* Page address translation */
868
            /* Primary table address */
869
            sdr = env->sdr1;
870
            pgidx = (eaddr & page_mask) >> target_page_bits;
871
#if defined(TARGET_PPC64)
872
            if (env->mmu_model & POWERPC_MMU_64) {
873
                htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
874
                /* XXX: this is false for 1 TB segments */
875
                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
876
            } else
877
#endif
878
            {
879
                htab_mask = sdr & 0x000001FF;
880
                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
881
            }
882
            mask = (htab_mask << sdr_sh) | sdr_mask;
883
            LOG_MMU("sdr " TARGET_FMT_plx " sh %d hash " TARGET_FMT_plx
884
                    " mask " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
885
                    sdr, sdr_sh, hash, mask, page_mask);
886
            ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask);
887
            /* Secondary table address */
888
            hash = (~hash) & vsid_mask;
889
            LOG_MMU("sdr " TARGET_FMT_plx " sh %d hash " TARGET_FMT_plx
890
                    " mask " TARGET_FMT_plx "\n", sdr, sdr_sh, hash, mask);
891
            ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
892
#if defined(TARGET_PPC64)
893
            if (env->mmu_model & POWERPC_MMU_64) {
894
                /* Only 5 bits of the page index are used in the AVPN */
895
                if (target_page_bits > 23) {
896
                    ctx->ptem = (vsid << 12) |
897
                                ((pgidx << (target_page_bits - 16)) & 0xF80);
898
                } else {
899
                    ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
900
                }
901
            } else
902
#endif
903
            {
904
                ctx->ptem = (vsid << 7) | (pgidx >> 10);
905
            }
906
            /* Initialize real address with an invalid value */
907
            ctx->raddr = (target_phys_addr_t)-1ULL;
908
            if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
909
                         env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
910
                /* Software TLB search */
911
                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
912
            } else {
913
                LOG_MMU("0 sdr1=" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " "
914
                        "api=" TARGET_FMT_lx " hash=" TARGET_FMT_plx
915
                        " pg_addr=" TARGET_FMT_plx "\n",
916
                        sdr, vsid, pgidx, hash, ctx->pg_addr[0]);
917
                /* Primary table lookup */
918
                ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
919
                if (ret < 0) {
920
                    /* Secondary table lookup */
921
                    if (eaddr != 0xEFFFFFFF)
922
                        LOG_MMU("1 sdr1=" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " "
923
                                "api=" TARGET_FMT_lx " hash=" TARGET_FMT_plx
924
                                " pg_addr=" TARGET_FMT_plx "\n", sdr, vsid,
925
                                pgidx, hash, ctx->pg_addr[1]);
926
                    ret2 = find_pte(env, ctx, 1, rw, type,
927
                                    target_page_bits);
928
                    if (ret2 != -1)
929
                        ret = ret2;
930
                }
931
            }
932
#if defined (DUMP_PAGE_TABLES)
933
            if (qemu_log_enabled()) {
934
                target_phys_addr_t curaddr;
935
                uint32_t a0, a1, a2, a3;
936
                qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
937
                         "\n", sdr, mask + 0x80);
938
                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
939
                     curaddr += 16) {
940
                    a0 = ldl_phys(curaddr);
941
                    a1 = ldl_phys(curaddr + 4);
942
                    a2 = ldl_phys(curaddr + 8);
943
                    a3 = ldl_phys(curaddr + 12);
944
                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
945
                        qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
946
                                 curaddr, a0, a1, a2, a3);
947
                    }
948
                }
949
            }
950
#endif
951
        } else {
952
            LOG_MMU("No access allowed\n");
953
            ret = -3;
954
        }
955
    } else {
956
        LOG_MMU("direct store...\n");
957
        /* Direct-store segment : absolutely *BUGGY* for now */
958
        switch (type) {
959
        case ACCESS_INT:
960
            /* Integer load/store : only access allowed */
961
            break;
962
        case ACCESS_CODE:
963
            /* No code fetch is allowed in direct-store areas */
964
            return -4;
965
        case ACCESS_FLOAT:
966
            /* Floating point load/store */
967
            return -4;
968
        case ACCESS_RES:
969
            /* lwarx, ldarx or srwcx. */
970
            return -4;
971
        case ACCESS_CACHE:
972
            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
973
            /* Should make the instruction do no-op.
974
             * As it already do no-op, it's quite easy :-)
975
             */
976
            ctx->raddr = eaddr;
977
            return 0;
978
        case ACCESS_EXT:
979
            /* eciwx or ecowx */
980
            return -4;
981
        default:
982
            qemu_log("ERROR: instruction should not need "
983
                        "address translation\n");
984
            return -4;
985
        }
986
        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
987
            ctx->raddr = eaddr;
988
            ret = 2;
989
        } else {
990
            ret = -2;
991
        }
992
    }
993

    
994
    return ret;
995
}
996

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

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

    
1027
    return 0;
1028
}
1029

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

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

    
1047
    return ret;
1048
}
1049

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

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

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

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

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

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

    
1146
    return ret;
1147
}
1148

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

    
1158
static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1159
                                          target_ulong address, int rw,
1160
                                          int access_type)
1161
{
1162
    ppcemb_tlb_t *tlb;
1163
    target_phys_addr_t raddr;
1164
    int i, prot, ret;
1165

    
1166
    ret = -1;
1167
    raddr = (target_phys_addr_t)-1ULL;
1168
    for (i = 0; i < env->nb_tlb; i++) {
1169
        tlb = &env->tlb[i].tlbe;
1170
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1171
                             env->spr[SPR_BOOKE_PID], 1, i) < 0)
1172
            continue;
1173
        if (msr_pr != 0)
1174
            prot = tlb->prot & 0xF;
1175
        else
1176
            prot = (tlb->prot >> 4) & 0xF;
1177
        /* Check the address space */
1178
        if (access_type == ACCESS_CODE) {
1179
            if (msr_ir != (tlb->attr & 1))
1180
                continue;
1181
            ctx->prot = prot;
1182
            if (prot & PAGE_EXEC) {
1183
                ret = 0;
1184
                break;
1185
            }
1186
            ret = -3;
1187
        } else {
1188
            if (msr_dr != (tlb->attr & 1))
1189
                continue;
1190
            ctx->prot = prot;
1191
            if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
1192
                ret = 0;
1193
                break;
1194
            }
1195
            ret = -2;
1196
        }
1197
    }
1198
    if (ret >= 0)
1199
        ctx->raddr = raddr;
1200

    
1201
    return ret;
1202
}
1203

    
1204
static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1205
                                 target_ulong eaddr, int rw)
1206
{
1207
    int in_plb, ret;
1208

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

    
1267
    return ret;
1268
}
1269

    
1270
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1271
                          int rw, int access_type)
1272
{
1273
    int ret;
1274

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

    
1338
    return ret;
1339
}
1340

    
1341
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1342
{
1343
    mmu_ctx_t ctx;
1344

    
1345
    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1346
        return -1;
1347

    
1348
    return ctx.raddr & TARGET_PAGE_MASK;
1349
}
1350

    
1351
/* Perform address translation */
1352
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1353
                              int mmu_idx, int is_softmmu)
1354
{
1355
    mmu_ctx_t ctx;
1356
    int access_type;
1357
    int ret = 0;
1358

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

    
1628
    return ret;
1629
}
1630

    
1631
/*****************************************************************************/
1632
/* BATs management */
1633
#if !defined(FLUSH_ALL_TLBS)
1634
static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1635
                                     target_ulong mask)
1636
{
1637
    target_ulong base, end, page;
1638

    
1639
    base = BATu & ~0x0001FFFF;
1640
    end = base + mask + 0x00020000;
1641
    LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1642
             TARGET_FMT_lx ")\n", base, end, mask);
1643
    for (page = base; page != end; page += TARGET_PAGE_SIZE)
1644
        tlb_flush_page(env, page);
1645
    LOG_BATS("Flush done\n");
1646
}
1647
#endif
1648

    
1649
static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1650
                                  target_ulong value)
1651
{
1652
    LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1653
             nr, ul == 0 ? 'u' : 'l', value, env->nip);
1654
}
1655

    
1656
void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1657
{
1658
    target_ulong mask;
1659

    
1660
    dump_store_bat(env, 'I', 0, nr, value);
1661
    if (env->IBAT[0][nr] != value) {
1662
        mask = (value << 15) & 0x0FFE0000UL;
1663
#if !defined(FLUSH_ALL_TLBS)
1664
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1665
#endif
1666
        /* When storing valid upper BAT, mask BEPI and BRPN
1667
         * and invalidate all TLBs covered by this BAT
1668
         */
1669
        mask = (value << 15) & 0x0FFE0000UL;
1670
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1671
            (value & ~0x0001FFFFUL & ~mask);
1672
        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1673
            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1674
#if !defined(FLUSH_ALL_TLBS)
1675
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1676
#else
1677
        tlb_flush(env, 1);
1678
#endif
1679
    }
1680
}
1681

    
1682
void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1683
{
1684
    dump_store_bat(env, 'I', 1, nr, value);
1685
    env->IBAT[1][nr] = value;
1686
}
1687

    
1688
void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1689
{
1690
    target_ulong mask;
1691

    
1692
    dump_store_bat(env, 'D', 0, nr, value);
1693
    if (env->DBAT[0][nr] != value) {
1694
        /* When storing valid upper BAT, mask BEPI and BRPN
1695
         * and invalidate all TLBs covered by this BAT
1696
         */
1697
        mask = (value << 15) & 0x0FFE0000UL;
1698
#if !defined(FLUSH_ALL_TLBS)
1699
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1700
#endif
1701
        mask = (value << 15) & 0x0FFE0000UL;
1702
        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1703
            (value & ~0x0001FFFFUL & ~mask);
1704
        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1705
            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1706
#if !defined(FLUSH_ALL_TLBS)
1707
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1708
#else
1709
        tlb_flush(env, 1);
1710
#endif
1711
    }
1712
}
1713

    
1714
void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1715
{
1716
    dump_store_bat(env, 'D', 1, nr, value);
1717
    env->DBAT[1][nr] = value;
1718
}
1719

    
1720
void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1721
{
1722
    target_ulong mask;
1723
#if defined(FLUSH_ALL_TLBS)
1724
    int do_inval;
1725
#endif
1726

    
1727
    dump_store_bat(env, 'I', 0, nr, value);
1728
    if (env->IBAT[0][nr] != value) {
1729
#if defined(FLUSH_ALL_TLBS)
1730
        do_inval = 0;
1731
#endif
1732
        mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1733
        if (env->IBAT[1][nr] & 0x40) {
1734
            /* Invalidate BAT only if it is valid */
1735
#if !defined(FLUSH_ALL_TLBS)
1736
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1737
#else
1738
            do_inval = 1;
1739
#endif
1740
        }
1741
        /* When storing valid upper BAT, mask BEPI and BRPN
1742
         * and invalidate all TLBs covered by this BAT
1743
         */
1744
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1745
            (value & ~0x0001FFFFUL & ~mask);
1746
        env->DBAT[0][nr] = env->IBAT[0][nr];
1747
        if (env->IBAT[1][nr] & 0x40) {
1748
#if !defined(FLUSH_ALL_TLBS)
1749
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1750
#else
1751
            do_inval = 1;
1752
#endif
1753
        }
1754
#if defined(FLUSH_ALL_TLBS)
1755
        if (do_inval)
1756
            tlb_flush(env, 1);
1757
#endif
1758
    }
1759
}
1760

    
1761
void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1762
{
1763
    target_ulong mask;
1764
#if defined(FLUSH_ALL_TLBS)
1765
    int do_inval;
1766
#endif
1767

    
1768
    dump_store_bat(env, 'I', 1, nr, value);
1769
    if (env->IBAT[1][nr] != value) {
1770
#if defined(FLUSH_ALL_TLBS)
1771
        do_inval = 0;
1772
#endif
1773
        if (env->IBAT[1][nr] & 0x40) {
1774
#if !defined(FLUSH_ALL_TLBS)
1775
            mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1776
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1777
#else
1778
            do_inval = 1;
1779
#endif
1780
        }
1781
        if (value & 0x40) {
1782
#if !defined(FLUSH_ALL_TLBS)
1783
            mask = (value << 17) & 0x0FFE0000UL;
1784
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1785
#else
1786
            do_inval = 1;
1787
#endif
1788
        }
1789
        env->IBAT[1][nr] = value;
1790
        env->DBAT[1][nr] = value;
1791
#if defined(FLUSH_ALL_TLBS)
1792
        if (do_inval)
1793
            tlb_flush(env, 1);
1794
#endif
1795
    }
1796
}
1797

    
1798
/*****************************************************************************/
1799
/* TLB management */
1800
void ppc_tlb_invalidate_all (CPUPPCState *env)
1801
{
1802
    switch (env->mmu_model) {
1803
    case POWERPC_MMU_SOFT_6xx:
1804
    case POWERPC_MMU_SOFT_74xx:
1805
        ppc6xx_tlb_invalidate_all(env);
1806
        break;
1807
    case POWERPC_MMU_SOFT_4xx:
1808
    case POWERPC_MMU_SOFT_4xx_Z:
1809
        ppc4xx_tlb_invalidate_all(env);
1810
        break;
1811
    case POWERPC_MMU_REAL:
1812
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1813
        break;
1814
    case POWERPC_MMU_MPC8xx:
1815
        /* XXX: TODO */
1816
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1817
        break;
1818
    case POWERPC_MMU_BOOKE:
1819
        tlb_flush(env, 1);
1820
        break;
1821
    case POWERPC_MMU_BOOKE_FSL:
1822
        /* XXX: TODO */
1823
        if (!kvm_enabled())
1824
            cpu_abort(env, "BookE MMU model is not implemented\n");
1825
        break;
1826
    case POWERPC_MMU_32B:
1827
    case POWERPC_MMU_601:
1828
#if defined(TARGET_PPC64)
1829
    case POWERPC_MMU_620:
1830
    case POWERPC_MMU_64B:
1831
#endif /* defined(TARGET_PPC64) */
1832
        tlb_flush(env, 1);
1833
        break;
1834
    default:
1835
        /* XXX: TODO */
1836
        cpu_abort(env, "Unknown MMU model\n");
1837
        break;
1838
    }
1839
}
1840

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

    
1916
/*****************************************************************************/
1917
/* Special registers manipulation */
1918
#if defined(TARGET_PPC64)
1919
void ppc_store_asr (CPUPPCState *env, target_ulong value)
1920
{
1921
    if (env->asr != value) {
1922
        env->asr = value;
1923
        tlb_flush(env, 1);
1924
    }
1925
}
1926
#endif
1927

    
1928
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
1929
{
1930
    LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
1931
    if (env->sdr1 != value) {
1932
        /* XXX: for PowerPC 64, should check that the HTABSIZE value
1933
         *      is <= 28
1934
         */
1935
        env->sdr1 = value;
1936
        tlb_flush(env, 1);
1937
    }
1938
}
1939

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2770
    qemu_init_vcpu(env);
2771

    
2772
    return env;
2773
}
2774

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