Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ bb4ea393

History | View | Annotate | Download (92.4 kB)

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

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

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

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

    
48

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

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

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

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

    
73

    
74
/*****************************************************************************/
75
/* PowerPC MMU emulation */
76

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

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

    
97
    return 1;
98
}
99

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

    
107
static inline void pte_invalidate(target_ulong *pte0)
108
{
109
    *pte0 &= ~0x80000000;
110
}
111

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

    
118
static inline void pte64_invalidate(target_ulong *pte0)
119
{
120
    *pte0 &= ~0x0000000000000001ULL;
121
}
122
#endif
123

    
124
#define PTE_PTEM_MASK 0x7FFFFFBF
125
#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
126
#if defined(TARGET_PPC64)
127
#define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
128
#define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
129
#endif
130

    
131
static inline int pp_check(int key, int pp, int nx)
132
{
133
    int access;
134

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

    
168
    return access;
169
}
170

    
171
static inline int check_prot(int prot, int rw, int access_type)
172
{
173
    int ret;
174

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

    
192
    return ret;
193
}
194

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

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

    
253
    return ret;
254
}
255

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

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

    
270
static inline int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
271
                                   int ret, int rw)
272
{
273
    int store = 0;
274

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

    
292
    return store;
293
}
294

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

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

    
309
    return nr;
310
}
311

    
312
static inline void ppc6xx_tlb_invalidate_all(CPUState *env)
313
{
314
    ppc6xx_tlb_t *tlb;
315
    int nr, max;
316

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

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

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

    
354
static inline void ppc6xx_tlb_invalidate_virt(CPUState *env,
355
                                              target_ulong eaddr, int is_code)
356
{
357
    __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
358
}
359

    
360
void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
361
                       target_ulong pte0, target_ulong pte1)
362
{
363
    ppc6xx_tlb_t *tlb;
364
    int nr;
365

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

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

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

    
437
    return ret;
438
}
439

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

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

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

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

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

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

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

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

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

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

    
646
    return ret;
647
}
648

    
649
static inline int find_pte32(mmu_ctx_t *ctx, int h, int rw, int type,
650
                             int target_page_bits)
651
{
652
    return _find_pte(ctx, 0, h, rw, type, target_page_bits);
653
}
654

    
655
#if defined(TARGET_PPC64)
656
static inline int find_pte64(mmu_ctx_t *ctx, int h, int rw, int type,
657
                             int target_page_bits)
658
{
659
    return _find_pte(ctx, 1, h, rw, type, target_page_bits);
660
}
661
#endif
662

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

    
671
    return find_pte32(ctx, h, rw, type, target_page_bits);
672
}
673

    
674
#if defined(TARGET_PPC64)
675
static ppc_slb_t *slb_get_entry(CPUPPCState *env, int nr)
676
{
677
    ppc_slb_t *retval = &env->slb[nr];
678

    
679
#if 0 // XXX implement bridge mode?
680
    if (env->spr[SPR_ASR] & 1) {
681
        target_phys_addr_t sr_base;
682

683
        sr_base = env->spr[SPR_ASR] & 0xfffffffffffff000;
684
        sr_base += (12 * nr);
685

686
        retval->tmp64 = ldq_phys(sr_base);
687
        retval->tmp = ldl_phys(sr_base + 8);
688
    }
689
#endif
690

    
691
    return retval;
692
}
693

    
694
static void slb_set_entry(CPUPPCState *env, int nr, ppc_slb_t *slb)
695
{
696
    ppc_slb_t *entry = &env->slb[nr];
697

    
698
    if (slb == entry)
699
        return;
700

    
701
    entry->tmp64 = slb->tmp64;
702
    entry->tmp = slb->tmp;
703
}
704

    
705
static inline int slb_is_valid(ppc_slb_t *slb)
706
{
707
    return (int)(slb->tmp64 & 0x0000000008000000ULL);
708
}
709

    
710
static inline void slb_invalidate(ppc_slb_t *slb)
711
{
712
    slb->tmp64 &= ~0x0000000008000000ULL;
713
}
714

    
715
static inline int slb_lookup(CPUPPCState *env, target_ulong eaddr,
716
                             target_ulong *vsid, target_ulong *page_mask,
717
                             int *attr, int *target_page_bits)
718
{
719
    target_ulong mask;
720
    int n, ret;
721

    
722
    ret = -5;
723
    LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
724
    mask = 0x0000000000000000ULL; /* Avoid gcc warning */
725
    for (n = 0; n < env->slb_nr; n++) {
726
        ppc_slb_t *slb = slb_get_entry(env, n);
727

    
728
        LOG_SLB("%s: seg %d %016" PRIx64 " %08"
729
                    PRIx32 "\n", __func__, n, slb->tmp64, slb->tmp);
730
        if (slb_is_valid(slb)) {
731
            /* SLB entry is valid */
732
            mask = 0xFFFFFFFFF0000000ULL;
733
            if (slb->tmp & 0x8) {
734
                /* 16 MB PTEs */
735
                if (target_page_bits)
736
                    *target_page_bits = 24;
737
            } else {
738
                /* 4 KB PTEs */
739
                if (target_page_bits)
740
                    *target_page_bits = TARGET_PAGE_BITS;
741
            }
742
            if ((eaddr & mask) == (slb->tmp64 & mask)) {
743
                /* SLB match */
744
                *vsid = ((slb->tmp64 << 24) | (slb->tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
745
                *page_mask = ~mask;
746
                *attr = slb->tmp & 0xFF;
747
                ret = n;
748
                break;
749
            }
750
        }
751
    }
752

    
753
    return ret;
754
}
755

    
756
void ppc_slb_invalidate_all (CPUPPCState *env)
757
{
758
    int n, do_invalidate;
759

    
760
    do_invalidate = 0;
761
    /* XXX: Warning: slbia never invalidates the first segment */
762
    for (n = 1; n < env->slb_nr; n++) {
763
        ppc_slb_t *slb = slb_get_entry(env, n);
764

    
765
        if (slb_is_valid(slb)) {
766
            slb_invalidate(slb);
767
            slb_set_entry(env, n, slb);
768
            /* XXX: given the fact that segment size is 256 MB or 1TB,
769
             *      and we still don't have a tlb_flush_mask(env, n, mask)
770
             *      in Qemu, we just invalidate all TLBs
771
             */
772
            do_invalidate = 1;
773
        }
774
    }
775
    if (do_invalidate)
776
        tlb_flush(env, 1);
777
}
778

    
779
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
780
{
781
    target_ulong vsid, page_mask;
782
    int attr;
783
    int n;
784

    
785
    n = slb_lookup(env, T0, &vsid, &page_mask, &attr, NULL);
786
    if (n >= 0) {
787
        ppc_slb_t *slb = slb_get_entry(env, n);
788

    
789
        if (slb_is_valid(slb)) {
790
            slb_invalidate(slb);
791
            slb_set_entry(env, n, slb);
792
            /* XXX: given the fact that segment size is 256 MB or 1TB,
793
             *      and we still don't have a tlb_flush_mask(env, n, mask)
794
             *      in Qemu, we just invalidate all TLBs
795
             */
796
            tlb_flush(env, 1);
797
        }
798
    }
799
}
800

    
801
target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
802
{
803
    target_ulong rt;
804
    ppc_slb_t *slb = slb_get_entry(env, slb_nr);
805

    
806
    if (slb_is_valid(slb)) {
807
        /* SLB entry is valid */
808
        /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
809
        rt = slb->tmp >> 8;             /* 65:88 => 40:63 */
810
        rt |= (slb->tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
811
        /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
812
        rt |= ((slb->tmp >> 4) & 0xF) << 27;
813
    } else {
814
        rt = 0;
815
    }
816
    LOG_SLB("%s: %016" PRIx64 " %08" PRIx32 " => %d "
817
            TARGET_FMT_lx "\n", __func__, slb->tmp64, slb->tmp, slb_nr, rt);
818

    
819
    return rt;
820
}
821

    
822
void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
823
{
824
    ppc_slb_t *slb;
825

    
826
    uint64_t vsid;
827
    uint64_t esid;
828
    int flags, valid, slb_nr;
829

    
830
    vsid = rs >> 12;
831
    flags = ((rs >> 8) & 0xf);
832

    
833
    esid = rb >> 28;
834
    valid = (rb & (1 << 27));
835
    slb_nr = rb & 0xfff;
836

    
837
    slb = slb_get_entry(env, slb_nr);
838
    slb->tmp64 = (esid << 28) | valid | (vsid >> 24);
839
    slb->tmp = (vsid << 8) | (flags << 3);
840

    
841
    LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
842
            " %08" PRIx32 "\n", __func__, slb_nr, rb, rs, slb->tmp64,
843
            slb->tmp);
844

    
845
    slb_set_entry(env, slb_nr, slb);
846
}
847
#endif /* defined(TARGET_PPC64) */
848

    
849
/* Perform segment based translation */
850
static inline target_phys_addr_t get_pgaddr(target_phys_addr_t sdr1,
851
                                            int sdr_sh,
852
                                            target_phys_addr_t hash,
853
                                            target_phys_addr_t mask)
854
{
855
    return (sdr1 & ((target_phys_addr_t)(-1ULL) << sdr_sh)) | (hash & mask);
856
}
857

    
858
static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
859
                              target_ulong eaddr, int rw, int type)
860
{
861
    target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
862
    target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
863
#if defined(TARGET_PPC64)
864
    int attr;
865
#endif
866
    int ds, vsid_sh, sdr_sh, pr, target_page_bits;
867
    int ret, ret2;
868

    
869
    pr = msr_pr;
870
#if defined(TARGET_PPC64)
871
    if (env->mmu_model & POWERPC_MMU_64) {
872
        LOG_MMU("Check SLBs\n");
873
        ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr,
874
                         &target_page_bits);
875
        if (ret < 0)
876
            return ret;
877
        ctx->key = ((attr & 0x40) && (pr != 0)) ||
878
            ((attr & 0x80) && (pr == 0)) ? 1 : 0;
879
        ds = 0;
880
        ctx->nx = attr & 0x10 ? 1 : 0;
881
        ctx->eaddr = eaddr;
882
        vsid_mask = 0x00003FFFFFFFFF80ULL;
883
        vsid_sh = 7;
884
        sdr_sh = 18;
885
        sdr_mask = 0x3FF80;
886
    } else
887
#endif /* defined(TARGET_PPC64) */
888
    {
889
        sr = env->sr[eaddr >> 28];
890
        page_mask = 0x0FFFFFFF;
891
        ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
892
                    ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
893
        ds = sr & 0x80000000 ? 1 : 0;
894
        ctx->nx = sr & 0x10000000 ? 1 : 0;
895
        vsid = sr & 0x00FFFFFF;
896
        vsid_mask = 0x01FFFFC0;
897
        vsid_sh = 6;
898
        sdr_sh = 16;
899
        sdr_mask = 0xFFC0;
900
        target_page_bits = TARGET_PAGE_BITS;
901
        LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
902
                TARGET_FMT_lx " lr=" TARGET_FMT_lx
903
                " ir=%d dr=%d pr=%d %d t=%d\n",
904
                eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
905
                (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
906
    }
907
    LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
908
            ctx->key, ds, ctx->nx, vsid);
909
    ret = -1;
910
    if (!ds) {
911
        /* Check if instruction fetch is allowed, if needed */
912
        if (type != ACCESS_CODE || ctx->nx == 0) {
913
            /* Page address translation */
914
            /* Primary table address */
915
            sdr = env->sdr1;
916
            pgidx = (eaddr & page_mask) >> target_page_bits;
917
#if defined(TARGET_PPC64)
918
            if (env->mmu_model & POWERPC_MMU_64) {
919
                htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
920
                /* XXX: this is false for 1 TB segments */
921
                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
922
            } else
923
#endif
924
            {
925
                htab_mask = sdr & 0x000001FF;
926
                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
927
            }
928
            mask = (htab_mask << sdr_sh) | sdr_mask;
929
            LOG_MMU("sdr " TARGET_FMT_plx " sh %d hash " TARGET_FMT_plx
930
                    " mask " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
931
                    sdr, sdr_sh, hash, mask, page_mask);
932
            ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask);
933
            /* Secondary table address */
934
            hash = (~hash) & vsid_mask;
935
            LOG_MMU("sdr " TARGET_FMT_plx " sh %d hash " TARGET_FMT_plx
936
                    " mask " TARGET_FMT_plx "\n", sdr, sdr_sh, hash, mask);
937
            ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
938
#if defined(TARGET_PPC64)
939
            if (env->mmu_model & POWERPC_MMU_64) {
940
                /* Only 5 bits of the page index are used in the AVPN */
941
                if (target_page_bits > 23) {
942
                    ctx->ptem = (vsid << 12) |
943
                                ((pgidx << (target_page_bits - 16)) & 0xF80);
944
                } else {
945
                    ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
946
                }
947
            } else
948
#endif
949
            {
950
                ctx->ptem = (vsid << 7) | (pgidx >> 10);
951
            }
952
            /* Initialize real address with an invalid value */
953
            ctx->raddr = (target_phys_addr_t)-1ULL;
954
            if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
955
                         env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
956
                /* Software TLB search */
957
                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
958
            } else {
959
                LOG_MMU("0 sdr1=" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " "
960
                        "api=" TARGET_FMT_lx " hash=" TARGET_FMT_plx
961
                        " pg_addr=" TARGET_FMT_plx "\n",
962
                        sdr, vsid, pgidx, hash, ctx->pg_addr[0]);
963
                /* Primary table lookup */
964
                ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
965
                if (ret < 0) {
966
                    /* Secondary table lookup */
967
                    if (eaddr != 0xEFFFFFFF)
968
                        LOG_MMU("1 sdr1=" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " "
969
                                "api=" TARGET_FMT_lx " hash=" TARGET_FMT_plx
970
                                " pg_addr=" TARGET_FMT_plx "\n", sdr, vsid,
971
                                pgidx, hash, ctx->pg_addr[1]);
972
                    ret2 = find_pte(env, ctx, 1, rw, type,
973
                                    target_page_bits);
974
                    if (ret2 != -1)
975
                        ret = ret2;
976
                }
977
            }
978
#if defined (DUMP_PAGE_TABLES)
979
            if (qemu_log_enabled()) {
980
                target_phys_addr_t curaddr;
981
                uint32_t a0, a1, a2, a3;
982
                qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
983
                         "\n", sdr, mask + 0x80);
984
                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
985
                     curaddr += 16) {
986
                    a0 = ldl_phys(curaddr);
987
                    a1 = ldl_phys(curaddr + 4);
988
                    a2 = ldl_phys(curaddr + 8);
989
                    a3 = ldl_phys(curaddr + 12);
990
                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
991
                        qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
992
                                 curaddr, a0, a1, a2, a3);
993
                    }
994
                }
995
            }
996
#endif
997
        } else {
998
            LOG_MMU("No access allowed\n");
999
            ret = -3;
1000
        }
1001
    } else {
1002
        LOG_MMU("direct store...\n");
1003
        /* Direct-store segment : absolutely *BUGGY* for now */
1004
        switch (type) {
1005
        case ACCESS_INT:
1006
            /* Integer load/store : only access allowed */
1007
            break;
1008
        case ACCESS_CODE:
1009
            /* No code fetch is allowed in direct-store areas */
1010
            return -4;
1011
        case ACCESS_FLOAT:
1012
            /* Floating point load/store */
1013
            return -4;
1014
        case ACCESS_RES:
1015
            /* lwarx, ldarx or srwcx. */
1016
            return -4;
1017
        case ACCESS_CACHE:
1018
            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
1019
            /* Should make the instruction do no-op.
1020
             * As it already do no-op, it's quite easy :-)
1021
             */
1022
            ctx->raddr = eaddr;
1023
            return 0;
1024
        case ACCESS_EXT:
1025
            /* eciwx or ecowx */
1026
            return -4;
1027
        default:
1028
            qemu_log("ERROR: instruction should not need "
1029
                        "address translation\n");
1030
            return -4;
1031
        }
1032
        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
1033
            ctx->raddr = eaddr;
1034
            ret = 2;
1035
        } else {
1036
            ret = -2;
1037
        }
1038
    }
1039

    
1040
    return ret;
1041
}
1042

    
1043
/* Generic TLB check function for embedded PowerPC implementations */
1044
static inline int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
1045
                                   target_phys_addr_t *raddrp,
1046
                                   target_ulong address, uint32_t pid, int ext,
1047
                                   int i)
1048
{
1049
    target_ulong mask;
1050

    
1051
    /* Check valid flag */
1052
    if (!(tlb->prot & PAGE_VALID)) {
1053
        return -1;
1054
    }
1055
    mask = ~(tlb->size - 1);
1056
    LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
1057
              " " TARGET_FMT_lx " %u\n", __func__, i, address, pid, tlb->EPN,
1058
              mask, (uint32_t)tlb->PID);
1059
    /* Check PID */
1060
    if (tlb->PID != 0 && tlb->PID != pid)
1061
        return -1;
1062
    /* Check effective address */
1063
    if ((address & mask) != tlb->EPN)
1064
        return -1;
1065
    *raddrp = (tlb->RPN & mask) | (address & ~mask);
1066
#if (TARGET_PHYS_ADDR_BITS >= 36)
1067
    if (ext) {
1068
        /* Extend the physical address to 36 bits */
1069
        *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1070
    }
1071
#endif
1072

    
1073
    return 0;
1074
}
1075

    
1076
/* Generic TLB search function for PowerPC embedded implementations */
1077
int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1078
{
1079
    ppcemb_tlb_t *tlb;
1080
    target_phys_addr_t raddr;
1081
    int i, ret;
1082

    
1083
    /* Default return value is no match */
1084
    ret = -1;
1085
    for (i = 0; i < env->nb_tlb; i++) {
1086
        tlb = &env->tlb[i].tlbe;
1087
        if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1088
            ret = i;
1089
            break;
1090
        }
1091
    }
1092

    
1093
    return ret;
1094
}
1095

    
1096
/* Helpers specific to PowerPC 40x implementations */
1097
static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
1098
{
1099
    ppcemb_tlb_t *tlb;
1100
    int i;
1101

    
1102
    for (i = 0; i < env->nb_tlb; i++) {
1103
        tlb = &env->tlb[i].tlbe;
1104
        tlb->prot &= ~PAGE_VALID;
1105
    }
1106
    tlb_flush(env, 1);
1107
}
1108

    
1109
static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
1110
                                              target_ulong eaddr, uint32_t pid)
1111
{
1112
#if !defined(FLUSH_ALL_TLBS)
1113
    ppcemb_tlb_t *tlb;
1114
    target_phys_addr_t raddr;
1115
    target_ulong page, end;
1116
    int i;
1117

    
1118
    for (i = 0; i < env->nb_tlb; i++) {
1119
        tlb = &env->tlb[i].tlbe;
1120
        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1121
            end = tlb->EPN + tlb->size;
1122
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1123
                tlb_flush_page(env, page);
1124
            tlb->prot &= ~PAGE_VALID;
1125
            break;
1126
        }
1127
    }
1128
#else
1129
    ppc4xx_tlb_invalidate_all(env);
1130
#endif
1131
}
1132

    
1133
static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1134
                                 target_ulong address, int rw, int access_type)
1135
{
1136
    ppcemb_tlb_t *tlb;
1137
    target_phys_addr_t raddr;
1138
    int i, ret, zsel, zpr, pr;
1139

    
1140
    ret = -1;
1141
    raddr = (target_phys_addr_t)-1ULL;
1142
    pr = msr_pr;
1143
    for (i = 0; i < env->nb_tlb; i++) {
1144
        tlb = &env->tlb[i].tlbe;
1145
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1146
                             env->spr[SPR_40x_PID], 0, i) < 0)
1147
            continue;
1148
        zsel = (tlb->attr >> 4) & 0xF;
1149
        zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
1150
        LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1151
                    __func__, i, zsel, zpr, rw, tlb->attr);
1152
        /* Check execute enable bit */
1153
        switch (zpr) {
1154
        case 0x2:
1155
            if (pr != 0)
1156
                goto check_perms;
1157
            /* No break here */
1158
        case 0x3:
1159
            /* All accesses granted */
1160
            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1161
            ret = 0;
1162
            break;
1163
        case 0x0:
1164
            if (pr != 0) {
1165
                /* Raise Zone protection fault.  */
1166
                env->spr[SPR_40x_ESR] = 1 << 22;
1167
                ctx->prot = 0;
1168
                ret = -2;
1169
                break;
1170
            }
1171
            /* No break here */
1172
        case 0x1:
1173
        check_perms:
1174
            /* Check from TLB entry */
1175
            ctx->prot = tlb->prot;
1176
            ret = check_prot(ctx->prot, rw, access_type);
1177
            if (ret == -2)
1178
                env->spr[SPR_40x_ESR] = 0;
1179
            break;
1180
        }
1181
        if (ret >= 0) {
1182
            ctx->raddr = raddr;
1183
            LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1184
                      " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1185
                      ret);
1186
            return 0;
1187
        }
1188
    }
1189
    LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1190
              " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1191

    
1192
    return ret;
1193
}
1194

    
1195
void store_40x_sler (CPUPPCState *env, uint32_t val)
1196
{
1197
    /* XXX: TO BE FIXED */
1198
    if (val != 0x00000000) {
1199
        cpu_abort(env, "Little-endian regions are not supported by now\n");
1200
    }
1201
    env->spr[SPR_405_SLER] = val;
1202
}
1203

    
1204
static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1205
                                          target_ulong address, int rw,
1206
                                          int access_type)
1207
{
1208
    ppcemb_tlb_t *tlb;
1209
    target_phys_addr_t raddr;
1210
    int i, prot, ret;
1211

    
1212
    ret = -1;
1213
    raddr = (target_phys_addr_t)-1ULL;
1214
    for (i = 0; i < env->nb_tlb; i++) {
1215
        tlb = &env->tlb[i].tlbe;
1216
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1217
                             env->spr[SPR_BOOKE_PID], 1, i) < 0)
1218
            continue;
1219
        if (msr_pr != 0)
1220
            prot = tlb->prot & 0xF;
1221
        else
1222
            prot = (tlb->prot >> 4) & 0xF;
1223
        /* Check the address space */
1224
        if (access_type == ACCESS_CODE) {
1225
            if (msr_ir != (tlb->attr & 1))
1226
                continue;
1227
            ctx->prot = prot;
1228
            if (prot & PAGE_EXEC) {
1229
                ret = 0;
1230
                break;
1231
            }
1232
            ret = -3;
1233
        } else {
1234
            if (msr_dr != (tlb->attr & 1))
1235
                continue;
1236
            ctx->prot = prot;
1237
            if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
1238
                ret = 0;
1239
                break;
1240
            }
1241
            ret = -2;
1242
        }
1243
    }
1244
    if (ret >= 0)
1245
        ctx->raddr = raddr;
1246

    
1247
    return ret;
1248
}
1249

    
1250
static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1251
                                 target_ulong eaddr, int rw)
1252
{
1253
    int in_plb, ret;
1254

    
1255
    ctx->raddr = eaddr;
1256
    ctx->prot = PAGE_READ | PAGE_EXEC;
1257
    ret = 0;
1258
    switch (env->mmu_model) {
1259
    case POWERPC_MMU_32B:
1260
    case POWERPC_MMU_601:
1261
    case POWERPC_MMU_SOFT_6xx:
1262
    case POWERPC_MMU_SOFT_74xx:
1263
    case POWERPC_MMU_SOFT_4xx:
1264
    case POWERPC_MMU_REAL:
1265
    case POWERPC_MMU_BOOKE:
1266
        ctx->prot |= PAGE_WRITE;
1267
        break;
1268
#if defined(TARGET_PPC64)
1269
    case POWERPC_MMU_620:
1270
    case POWERPC_MMU_64B:
1271
        /* Real address are 60 bits long */
1272
        ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1273
        ctx->prot |= PAGE_WRITE;
1274
        break;
1275
#endif
1276
    case POWERPC_MMU_SOFT_4xx_Z:
1277
        if (unlikely(msr_pe != 0)) {
1278
            /* 403 family add some particular protections,
1279
             * using PBL/PBU registers for accesses with no translation.
1280
             */
1281
            in_plb =
1282
                /* Check PLB validity */
1283
                (env->pb[0] < env->pb[1] &&
1284
                 /* and address in plb area */
1285
                 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1286
                (env->pb[2] < env->pb[3] &&
1287
                 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1288
            if (in_plb ^ msr_px) {
1289
                /* Access in protected area */
1290
                if (rw == 1) {
1291
                    /* Access is not allowed */
1292
                    ret = -2;
1293
                }
1294
            } else {
1295
                /* Read-write access is allowed */
1296
                ctx->prot |= PAGE_WRITE;
1297
            }
1298
        }
1299
        break;
1300
    case POWERPC_MMU_MPC8xx:
1301
        /* XXX: TODO */
1302
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1303
        break;
1304
    case POWERPC_MMU_BOOKE_FSL:
1305
        /* XXX: TODO */
1306
        cpu_abort(env, "BookE FSL MMU model not implemented\n");
1307
        break;
1308
    default:
1309
        cpu_abort(env, "Unknown or invalid MMU model\n");
1310
        return -1;
1311
    }
1312

    
1313
    return ret;
1314
}
1315

    
1316
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1317
                          int rw, int access_type)
1318
{
1319
    int ret;
1320

    
1321
#if 0
1322
    qemu_log("%s\n", __func__);
1323
#endif
1324
    if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1325
        (access_type != ACCESS_CODE && msr_dr == 0)) {
1326
        if (env->mmu_model == POWERPC_MMU_BOOKE) {
1327
            /* The BookE MMU always performs address translation. The
1328
               IS and DS bits only affect the address space.  */
1329
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1330
                                                rw, access_type);
1331
        } else {
1332
            /* No address translation.  */
1333
            ret = check_physical(env, ctx, eaddr, rw);
1334
        }
1335
    } else {
1336
        ret = -1;
1337
        switch (env->mmu_model) {
1338
        case POWERPC_MMU_32B:
1339
        case POWERPC_MMU_601:
1340
        case POWERPC_MMU_SOFT_6xx:
1341
        case POWERPC_MMU_SOFT_74xx:
1342
            /* Try to find a BAT */
1343
            if (env->nb_BATs != 0)
1344
                ret = get_bat(env, ctx, eaddr, rw, access_type);
1345
#if defined(TARGET_PPC64)
1346
        case POWERPC_MMU_620:
1347
        case POWERPC_MMU_64B:
1348
#endif
1349
            if (ret < 0) {
1350
                /* We didn't match any BAT entry or don't have BATs */
1351
                ret = get_segment(env, ctx, eaddr, rw, access_type);
1352
            }
1353
            break;
1354
        case POWERPC_MMU_SOFT_4xx:
1355
        case POWERPC_MMU_SOFT_4xx_Z:
1356
            ret = mmu40x_get_physical_address(env, ctx, eaddr,
1357
                                              rw, access_type);
1358
            break;
1359
        case POWERPC_MMU_BOOKE:
1360
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1361
                                                rw, access_type);
1362
            break;
1363
        case POWERPC_MMU_MPC8xx:
1364
            /* XXX: TODO */
1365
            cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1366
            break;
1367
        case POWERPC_MMU_BOOKE_FSL:
1368
            /* XXX: TODO */
1369
            cpu_abort(env, "BookE FSL MMU model not implemented\n");
1370
            return -1;
1371
        case POWERPC_MMU_REAL:
1372
            cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1373
            return -1;
1374
        default:
1375
            cpu_abort(env, "Unknown or invalid MMU model\n");
1376
            return -1;
1377
        }
1378
    }
1379
#if 0
1380
    qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1381
             __func__, eaddr, ret, ctx->raddr);
1382
#endif
1383

    
1384
    return ret;
1385
}
1386

    
1387
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1388
{
1389
    mmu_ctx_t ctx;
1390

    
1391
    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1392
        return -1;
1393

    
1394
    return ctx.raddr & TARGET_PAGE_MASK;
1395
}
1396

    
1397
/* Perform address translation */
1398
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1399
                              int mmu_idx, int is_softmmu)
1400
{
1401
    mmu_ctx_t ctx;
1402
    int access_type;
1403
    int ret = 0;
1404

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

    
1674
    return ret;
1675
}
1676

    
1677
/*****************************************************************************/
1678
/* BATs management */
1679
#if !defined(FLUSH_ALL_TLBS)
1680
static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1681
                                     target_ulong mask)
1682
{
1683
    target_ulong base, end, page;
1684

    
1685
    base = BATu & ~0x0001FFFF;
1686
    end = base + mask + 0x00020000;
1687
    LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1688
             TARGET_FMT_lx ")\n", base, end, mask);
1689
    for (page = base; page != end; page += TARGET_PAGE_SIZE)
1690
        tlb_flush_page(env, page);
1691
    LOG_BATS("Flush done\n");
1692
}
1693
#endif
1694

    
1695
static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1696
                                  target_ulong value)
1697
{
1698
    LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1699
             nr, ul == 0 ? 'u' : 'l', value, env->nip);
1700
}
1701

    
1702
void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1703
{
1704
    target_ulong mask;
1705

    
1706
    dump_store_bat(env, 'I', 0, nr, value);
1707
    if (env->IBAT[0][nr] != value) {
1708
        mask = (value << 15) & 0x0FFE0000UL;
1709
#if !defined(FLUSH_ALL_TLBS)
1710
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1711
#endif
1712
        /* When storing valid upper BAT, mask BEPI and BRPN
1713
         * and invalidate all TLBs covered by this BAT
1714
         */
1715
        mask = (value << 15) & 0x0FFE0000UL;
1716
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1717
            (value & ~0x0001FFFFUL & ~mask);
1718
        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1719
            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1720
#if !defined(FLUSH_ALL_TLBS)
1721
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1722
#else
1723
        tlb_flush(env, 1);
1724
#endif
1725
    }
1726
}
1727

    
1728
void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1729
{
1730
    dump_store_bat(env, 'I', 1, nr, value);
1731
    env->IBAT[1][nr] = value;
1732
}
1733

    
1734
void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1735
{
1736
    target_ulong mask;
1737

    
1738
    dump_store_bat(env, 'D', 0, nr, value);
1739
    if (env->DBAT[0][nr] != value) {
1740
        /* When storing valid upper BAT, mask BEPI and BRPN
1741
         * and invalidate all TLBs covered by this BAT
1742
         */
1743
        mask = (value << 15) & 0x0FFE0000UL;
1744
#if !defined(FLUSH_ALL_TLBS)
1745
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1746
#endif
1747
        mask = (value << 15) & 0x0FFE0000UL;
1748
        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1749
            (value & ~0x0001FFFFUL & ~mask);
1750
        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1751
            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1752
#if !defined(FLUSH_ALL_TLBS)
1753
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1754
#else
1755
        tlb_flush(env, 1);
1756
#endif
1757
    }
1758
}
1759

    
1760
void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1761
{
1762
    dump_store_bat(env, 'D', 1, nr, value);
1763
    env->DBAT[1][nr] = value;
1764
}
1765

    
1766
void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1767
{
1768
    target_ulong mask;
1769
#if defined(FLUSH_ALL_TLBS)
1770
    int do_inval;
1771
#endif
1772

    
1773
    dump_store_bat(env, 'I', 0, nr, value);
1774
    if (env->IBAT[0][nr] != value) {
1775
#if defined(FLUSH_ALL_TLBS)
1776
        do_inval = 0;
1777
#endif
1778
        mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1779
        if (env->IBAT[1][nr] & 0x40) {
1780
            /* Invalidate BAT only if it is valid */
1781
#if !defined(FLUSH_ALL_TLBS)
1782
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1783
#else
1784
            do_inval = 1;
1785
#endif
1786
        }
1787
        /* When storing valid upper BAT, mask BEPI and BRPN
1788
         * and invalidate all TLBs covered by this BAT
1789
         */
1790
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1791
            (value & ~0x0001FFFFUL & ~mask);
1792
        env->DBAT[0][nr] = env->IBAT[0][nr];
1793
        if (env->IBAT[1][nr] & 0x40) {
1794
#if !defined(FLUSH_ALL_TLBS)
1795
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1796
#else
1797
            do_inval = 1;
1798
#endif
1799
        }
1800
#if defined(FLUSH_ALL_TLBS)
1801
        if (do_inval)
1802
            tlb_flush(env, 1);
1803
#endif
1804
    }
1805
}
1806

    
1807
void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1808
{
1809
    target_ulong mask;
1810
#if defined(FLUSH_ALL_TLBS)
1811
    int do_inval;
1812
#endif
1813

    
1814
    dump_store_bat(env, 'I', 1, nr, value);
1815
    if (env->IBAT[1][nr] != value) {
1816
#if defined(FLUSH_ALL_TLBS)
1817
        do_inval = 0;
1818
#endif
1819
        if (env->IBAT[1][nr] & 0x40) {
1820
#if !defined(FLUSH_ALL_TLBS)
1821
            mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1822
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1823
#else
1824
            do_inval = 1;
1825
#endif
1826
        }
1827
        if (value & 0x40) {
1828
#if !defined(FLUSH_ALL_TLBS)
1829
            mask = (value << 17) & 0x0FFE0000UL;
1830
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1831
#else
1832
            do_inval = 1;
1833
#endif
1834
        }
1835
        env->IBAT[1][nr] = value;
1836
        env->DBAT[1][nr] = value;
1837
#if defined(FLUSH_ALL_TLBS)
1838
        if (do_inval)
1839
            tlb_flush(env, 1);
1840
#endif
1841
    }
1842
}
1843

    
1844
/*****************************************************************************/
1845
/* TLB management */
1846
void ppc_tlb_invalidate_all (CPUPPCState *env)
1847
{
1848
    switch (env->mmu_model) {
1849
    case POWERPC_MMU_SOFT_6xx:
1850
    case POWERPC_MMU_SOFT_74xx:
1851
        ppc6xx_tlb_invalidate_all(env);
1852
        break;
1853
    case POWERPC_MMU_SOFT_4xx:
1854
    case POWERPC_MMU_SOFT_4xx_Z:
1855
        ppc4xx_tlb_invalidate_all(env);
1856
        break;
1857
    case POWERPC_MMU_REAL:
1858
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1859
        break;
1860
    case POWERPC_MMU_MPC8xx:
1861
        /* XXX: TODO */
1862
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1863
        break;
1864
    case POWERPC_MMU_BOOKE:
1865
        tlb_flush(env, 1);
1866
        break;
1867
    case POWERPC_MMU_BOOKE_FSL:
1868
        /* XXX: TODO */
1869
        if (!kvm_enabled())
1870
            cpu_abort(env, "BookE MMU model is not implemented\n");
1871
        break;
1872
    case POWERPC_MMU_32B:
1873
    case POWERPC_MMU_601:
1874
#if defined(TARGET_PPC64)
1875
    case POWERPC_MMU_620:
1876
    case POWERPC_MMU_64B:
1877
#endif /* defined(TARGET_PPC64) */
1878
        tlb_flush(env, 1);
1879
        break;
1880
    default:
1881
        /* XXX: TODO */
1882
        cpu_abort(env, "Unknown MMU model\n");
1883
        break;
1884
    }
1885
}
1886

    
1887
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
1888
{
1889
#if !defined(FLUSH_ALL_TLBS)
1890
    addr &= TARGET_PAGE_MASK;
1891
    switch (env->mmu_model) {
1892
    case POWERPC_MMU_SOFT_6xx:
1893
    case POWERPC_MMU_SOFT_74xx:
1894
        ppc6xx_tlb_invalidate_virt(env, addr, 0);
1895
        if (env->id_tlbs == 1)
1896
            ppc6xx_tlb_invalidate_virt(env, addr, 1);
1897
        break;
1898
    case POWERPC_MMU_SOFT_4xx:
1899
    case POWERPC_MMU_SOFT_4xx_Z:
1900
        ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
1901
        break;
1902
    case POWERPC_MMU_REAL:
1903
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1904
        break;
1905
    case POWERPC_MMU_MPC8xx:
1906
        /* XXX: TODO */
1907
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1908
        break;
1909
    case POWERPC_MMU_BOOKE:
1910
        /* XXX: TODO */
1911
        cpu_abort(env, "BookE MMU model is not implemented\n");
1912
        break;
1913
    case POWERPC_MMU_BOOKE_FSL:
1914
        /* XXX: TODO */
1915
        cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1916
        break;
1917
    case POWERPC_MMU_32B:
1918
    case POWERPC_MMU_601:
1919
        /* tlbie invalidate TLBs for all segments */
1920
        addr &= ~((target_ulong)-1ULL << 28);
1921
        /* XXX: this case should be optimized,
1922
         * giving a mask to tlb_flush_page
1923
         */
1924
        tlb_flush_page(env, addr | (0x0 << 28));
1925
        tlb_flush_page(env, addr | (0x1 << 28));
1926
        tlb_flush_page(env, addr | (0x2 << 28));
1927
        tlb_flush_page(env, addr | (0x3 << 28));
1928
        tlb_flush_page(env, addr | (0x4 << 28));
1929
        tlb_flush_page(env, addr | (0x5 << 28));
1930
        tlb_flush_page(env, addr | (0x6 << 28));
1931
        tlb_flush_page(env, addr | (0x7 << 28));
1932
        tlb_flush_page(env, addr | (0x8 << 28));
1933
        tlb_flush_page(env, addr | (0x9 << 28));
1934
        tlb_flush_page(env, addr | (0xA << 28));
1935
        tlb_flush_page(env, addr | (0xB << 28));
1936
        tlb_flush_page(env, addr | (0xC << 28));
1937
        tlb_flush_page(env, addr | (0xD << 28));
1938
        tlb_flush_page(env, addr | (0xE << 28));
1939
        tlb_flush_page(env, addr | (0xF << 28));
1940
        break;
1941
#if defined(TARGET_PPC64)
1942
    case POWERPC_MMU_620:
1943
    case POWERPC_MMU_64B:
1944
        /* tlbie invalidate TLBs for all segments */
1945
        /* XXX: given the fact that there are too many segments to invalidate,
1946
         *      and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
1947
         *      we just invalidate all TLBs
1948
         */
1949
        tlb_flush(env, 1);
1950
        break;
1951
#endif /* defined(TARGET_PPC64) */
1952
    default:
1953
        /* XXX: TODO */
1954
        cpu_abort(env, "Unknown MMU model\n");
1955
        break;
1956
    }
1957
#else
1958
    ppc_tlb_invalidate_all(env);
1959
#endif
1960
}
1961

    
1962
/*****************************************************************************/
1963
/* Special registers manipulation */
1964
#if defined(TARGET_PPC64)
1965
void ppc_store_asr (CPUPPCState *env, target_ulong value)
1966
{
1967
    if (env->asr != value) {
1968
        env->asr = value;
1969
        tlb_flush(env, 1);
1970
    }
1971
}
1972
#endif
1973

    
1974
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
1975
{
1976
    LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
1977
    if (env->sdr1 != value) {
1978
        /* XXX: for PowerPC 64, should check that the HTABSIZE value
1979
         *      is <= 28
1980
         */
1981
        env->sdr1 = value;
1982
        tlb_flush(env, 1);
1983
    }
1984
}
1985

    
1986
#if defined(TARGET_PPC64)
1987
target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
1988
{
1989
    // XXX
1990
    return 0;
1991
}
1992
#endif
1993

    
1994
void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1995
{
1996
    LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
1997
            srnum, value, env->sr[srnum]);
1998
#if defined(TARGET_PPC64)
1999
    if (env->mmu_model & POWERPC_MMU_64) {
2000
        uint64_t rb = 0, rs = 0;
2001

    
2002
        /* ESID = srnum */
2003
        rb |= ((uint32_t)srnum & 0xf) << 28;
2004
        /* Set the valid bit */
2005
        rb |= 1 << 27;
2006
        /* Index = ESID */
2007
        rb |= (uint32_t)srnum;
2008

    
2009
        /* VSID = VSID */
2010
        rs |= (value & 0xfffffff) << 12;
2011
        /* flags = flags */
2012
        rs |= ((value >> 27) & 0xf) << 9;
2013

    
2014
        ppc_store_slb(env, rb, rs);
2015
    } else
2016
#endif
2017
    if (env->sr[srnum] != value) {
2018
        env->sr[srnum] = value;
2019
/* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2020
   flusing the whole TLB. */
2021
#if !defined(FLUSH_ALL_TLBS) && 0
2022
        {
2023
            target_ulong page, end;
2024
            /* Invalidate 256 MB of virtual memory */
2025
            page = (16 << 20) * srnum;
2026
            end = page + (16 << 20);
2027
            for (; page != end; page += TARGET_PAGE_SIZE)
2028
                tlb_flush_page(env, page);
2029
        }
2030
#else
2031
        tlb_flush(env, 1);
2032
#endif
2033
    }
2034
}
2035
#endif /* !defined (CONFIG_USER_ONLY) */
2036

    
2037
/* GDBstub can read and write MSR... */
2038
void ppc_store_msr (CPUPPCState *env, target_ulong value)
2039
{
2040
    hreg_store_msr(env, value, 0);
2041
}
2042

    
2043
/*****************************************************************************/
2044
/* Exception processing */
2045
#if defined (CONFIG_USER_ONLY)
2046
void do_interrupt (CPUState *env)
2047
{
2048
    env->exception_index = POWERPC_EXCP_NONE;
2049
    env->error_code = 0;
2050
}
2051

    
2052
void ppc_hw_interrupt (CPUState *env)
2053
{
2054
    env->exception_index = POWERPC_EXCP_NONE;
2055
    env->error_code = 0;
2056
}
2057
#else /* defined (CONFIG_USER_ONLY) */
2058
static inline void dump_syscall(CPUState *env)
2059
{
2060
    qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2061
                  " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2062
                  " nip=" TARGET_FMT_lx "\n",
2063
                  ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2064
                  ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2065
                  ppc_dump_gpr(env, 6), env->nip);
2066
}
2067

    
2068
/* Note that this function should be greatly optimized
2069
 * when called with a constant excp, from ppc_hw_interrupt
2070
 */
2071
static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2072
{
2073
    target_ulong msr, new_msr, vector;
2074
    int srr0, srr1, asrr0, asrr1;
2075
    int lpes0, lpes1, lev;
2076

    
2077
    if (0) {
2078
        /* XXX: find a suitable condition to enable the hypervisor mode */
2079
        lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2080
        lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2081
    } else {
2082
        /* Those values ensure we won't enter the hypervisor mode */
2083
        lpes0 = 0;
2084
        lpes1 = 1;
2085
    }
2086

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

    
2090
    /* new srr1 value excluding must-be-zero bits */
2091
    msr = env->msr & ~0x783f0000ULL;
2092

    
2093
    /* new interrupt handler msr */
2094
    new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2095

    
2096
    /* target registers */
2097
    srr0 = SPR_SRR0;
2098
    srr1 = SPR_SRR1;
2099
    asrr0 = -1;
2100
    asrr1 = -1;
2101

    
2102
    switch (excp) {
2103
    case POWERPC_EXCP_NONE:
2104
        /* Should never happen */
2105
        return;
2106
    case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
2107
        switch (excp_model) {
2108
        case POWERPC_EXCP_40x:
2109
            srr0 = SPR_40x_SRR2;
2110
            srr1 = SPR_40x_SRR3;
2111
            break;
2112
        case POWERPC_EXCP_BOOKE:
2113
            srr0 = SPR_BOOKE_CSRR0;
2114
            srr1 = SPR_BOOKE_CSRR1;
2115
            break;
2116
        case POWERPC_EXCP_G2:
2117
            break;
2118
        default:
2119
            goto excp_invalid;
2120
        }
2121
        goto store_next;
2122
    case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
2123
        if (msr_me == 0) {
2124
            /* Machine check exception is not enabled.
2125
             * Enter checkstop state.
2126
             */
2127
            if (qemu_log_enabled()) {
2128
                qemu_log("Machine check while not allowed. "
2129
                        "Entering checkstop state\n");
2130
            } else {
2131
                fprintf(stderr, "Machine check while not allowed. "
2132
                        "Entering checkstop state\n");
2133
            }
2134
            env->halted = 1;
2135
            env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2136
        }
2137
        if (0) {
2138
            /* XXX: find a suitable condition to enable the hypervisor mode */
2139
            new_msr |= (target_ulong)MSR_HVB;
2140
        }
2141

    
2142
        /* machine check exceptions don't have ME set */
2143
        new_msr &= ~((target_ulong)1 << MSR_ME);
2144

    
2145
        /* XXX: should also have something loaded in DAR / DSISR */
2146
        switch (excp_model) {
2147
        case POWERPC_EXCP_40x:
2148
            srr0 = SPR_40x_SRR2;
2149
            srr1 = SPR_40x_SRR3;
2150
            break;
2151
        case POWERPC_EXCP_BOOKE:
2152
            srr0 = SPR_BOOKE_MCSRR0;
2153
            srr1 = SPR_BOOKE_MCSRR1;
2154
            asrr0 = SPR_BOOKE_CSRR0;
2155
            asrr1 = SPR_BOOKE_CSRR1;
2156
            break;
2157
        default:
2158
            break;
2159
        }
2160
        goto store_next;
2161
    case POWERPC_EXCP_DSI:       /* Data storage exception                   */
2162
        LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2163
                 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2164
        if (lpes1 == 0)
2165
            new_msr |= (target_ulong)MSR_HVB;
2166
        goto store_next;
2167
    case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
2168
        LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2169
                 "\n", msr, env->nip);
2170
        if (lpes1 == 0)
2171
            new_msr |= (target_ulong)MSR_HVB;
2172
        msr |= env->error_code;
2173
        goto store_next;
2174
    case POWERPC_EXCP_EXTERNAL:  /* External input                           */
2175
        if (lpes0 == 1)
2176
            new_msr |= (target_ulong)MSR_HVB;
2177
        goto store_next;
2178
    case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
2179
        if (lpes1 == 0)
2180
            new_msr |= (target_ulong)MSR_HVB;
2181
        /* XXX: this is false */
2182
        /* Get rS/rD and rA from faulting opcode */
2183
        env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2184
        goto store_current;
2185
    case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
2186
        switch (env->error_code & ~0xF) {
2187
        case POWERPC_EXCP_FP:
2188
            if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2189
                LOG_EXCP("Ignore floating point exception\n");
2190
                env->exception_index = POWERPC_EXCP_NONE;
2191
                env->error_code = 0;
2192
                return;
2193
            }
2194
            if (lpes1 == 0)
2195
                new_msr |= (target_ulong)MSR_HVB;
2196
            msr |= 0x00100000;
2197
            if (msr_fe0 == msr_fe1)
2198
                goto store_next;
2199
            msr |= 0x00010000;
2200
            break;
2201
        case POWERPC_EXCP_INVAL:
2202
            LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2203
            if (lpes1 == 0)
2204
                new_msr |= (target_ulong)MSR_HVB;
2205
            msr |= 0x00080000;
2206
            break;
2207
        case POWERPC_EXCP_PRIV:
2208
            if (lpes1 == 0)
2209
                new_msr |= (target_ulong)MSR_HVB;
2210
            msr |= 0x00040000;
2211
            break;
2212
        case POWERPC_EXCP_TRAP:
2213
            if (lpes1 == 0)
2214
                new_msr |= (target_ulong)MSR_HVB;
2215
            msr |= 0x00020000;
2216
            break;
2217
        default:
2218
            /* Should never occur */
2219
            cpu_abort(env, "Invalid program exception %d. Aborting\n",
2220
                      env->error_code);
2221
            break;
2222
        }
2223
        goto store_current;
2224
    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
2225
        if (lpes1 == 0)
2226
            new_msr |= (target_ulong)MSR_HVB;
2227
        goto store_current;
2228
    case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
2229
        dump_syscall(env);
2230
        lev = env->error_code;
2231
        if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2232
            new_msr |= (target_ulong)MSR_HVB;
2233
        goto store_next;
2234
    case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
2235
        goto store_current;
2236
    case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
2237
        if (lpes1 == 0)
2238
            new_msr |= (target_ulong)MSR_HVB;
2239
        goto store_next;
2240
    case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
2241
        /* FIT on 4xx */
2242
        LOG_EXCP("FIT exception\n");
2243
        goto store_next;
2244
    case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
2245
        LOG_EXCP("WDT exception\n");
2246
        switch (excp_model) {
2247
        case POWERPC_EXCP_BOOKE:
2248
            srr0 = SPR_BOOKE_CSRR0;
2249
            srr1 = SPR_BOOKE_CSRR1;
2250
            break;
2251
        default:
2252
            break;
2253
        }
2254
        goto store_next;
2255
    case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
2256
        goto store_next;
2257
    case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
2258
        goto store_next;
2259
    case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
2260
        switch (excp_model) {
2261
        case POWERPC_EXCP_BOOKE:
2262
            srr0 = SPR_BOOKE_DSRR0;
2263
            srr1 = SPR_BOOKE_DSRR1;
2264
            asrr0 = SPR_BOOKE_CSRR0;
2265
            asrr1 = SPR_BOOKE_CSRR1;
2266
            break;
2267
        default:
2268
            break;
2269
        }
2270
        /* XXX: TODO */
2271
        cpu_abort(env, "Debug exception is not implemented yet !\n");
2272
        goto store_next;
2273
    case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
2274
        goto store_current;
2275
    case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
2276
        /* XXX: TODO */
2277
        cpu_abort(env, "Embedded floating point data exception "
2278
                  "is not implemented yet !\n");
2279
        goto store_next;
2280
    case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
2281
        /* XXX: TODO */
2282
        cpu_abort(env, "Embedded floating point round exception "
2283
                  "is not implemented yet !\n");
2284
        goto store_next;
2285
    case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
2286
        /* XXX: TODO */
2287
        cpu_abort(env,
2288
                  "Performance counter exception is not implemented yet !\n");
2289
        goto store_next;
2290
    case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
2291
        /* XXX: TODO */
2292
        cpu_abort(env,
2293
                  "Embedded doorbell interrupt is not implemented yet !\n");
2294
        goto store_next;
2295
    case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
2296
        switch (excp_model) {
2297
        case POWERPC_EXCP_BOOKE:
2298
            srr0 = SPR_BOOKE_CSRR0;
2299
            srr1 = SPR_BOOKE_CSRR1;
2300
            break;
2301
        default:
2302
            break;
2303
        }
2304
        /* XXX: TODO */
2305
        cpu_abort(env, "Embedded doorbell critical interrupt "
2306
                  "is not implemented yet !\n");
2307
        goto store_next;
2308
    case POWERPC_EXCP_RESET:     /* System reset exception                   */
2309
        if (msr_pow) {
2310
            /* indicate that we resumed from power save mode */
2311
            msr |= 0x10000;
2312
        } else {
2313
            new_msr &= ~((target_ulong)1 << MSR_ME);
2314
        }
2315

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

    
2577
    if (msr_ile) {
2578
        new_msr |= (target_ulong)1 << MSR_LE;
2579
    }
2580

    
2581
    /* Jump to handler */
2582
    vector = env->excp_vectors[excp];
2583
    if (vector == (target_ulong)-1ULL) {
2584
        cpu_abort(env, "Raised an exception without defined vector %d\n",
2585
                  excp);
2586
    }
2587
    vector |= env->excp_prefix;
2588
#if defined(TARGET_PPC64)
2589
    if (excp_model == POWERPC_EXCP_BOOKE) {
2590
        if (!msr_icm) {
2591
            vector = (uint32_t)vector;
2592
        } else {
2593
            new_msr |= (target_ulong)1 << MSR_CM;
2594
        }
2595
    } else {
2596
        if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2597
            vector = (uint32_t)vector;
2598
        } else {
2599
            new_msr |= (target_ulong)1 << MSR_SF;
2600
        }
2601
    }
2602
#endif
2603
    /* XXX: we don't use hreg_store_msr here as already have treated
2604
     *      any special case that could occur. Just store MSR and update hflags
2605
     */
2606
    env->msr = new_msr & env->msr_mask;
2607
    hreg_compute_hflags(env);
2608
    env->nip = vector;
2609
    /* Reset exception state */
2610
    env->exception_index = POWERPC_EXCP_NONE;
2611
    env->error_code = 0;
2612

    
2613
    if (env->mmu_model == POWERPC_MMU_BOOKE) {
2614
        /* XXX: The BookE changes address space when switching modes,
2615
                we should probably implement that as different MMU indexes,
2616
                but for the moment we do it the slow way and flush all.  */
2617
        tlb_flush(env, 1);
2618
    }
2619
}
2620

    
2621
void do_interrupt (CPUState *env)
2622
{
2623
    powerpc_excp(env, env->excp_model, env->exception_index);
2624
}
2625

    
2626
void ppc_hw_interrupt (CPUPPCState *env)
2627
{
2628
    int hdice;
2629

    
2630
#if 0
2631
    qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
2632
                __func__, env, env->pending_interrupts,
2633
                env->interrupt_request, (int)msr_me, (int)msr_ee);
2634
#endif
2635
    /* External reset */
2636
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
2637
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
2638
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
2639
        return;
2640
    }
2641
    /* Machine check exception */
2642
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
2643
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
2644
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
2645
        return;
2646
    }
2647
#if 0 /* TODO */
2648
    /* External debug exception */
2649
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
2650
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2651
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
2652
        return;
2653
    }
2654
#endif
2655
    if (0) {
2656
        /* XXX: find a suitable condition to enable the hypervisor mode */
2657
        hdice = env->spr[SPR_LPCR] & 1;
2658
    } else {
2659
        hdice = 0;
2660
    }
2661
    if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
2662
        /* Hypervisor decrementer exception */
2663
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
2664
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
2665
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
2666
            return;
2667
        }
2668
    }
2669
    if (msr_ce != 0) {
2670
        /* External critical interrupt */
2671
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
2672
            /* Taking a critical external interrupt does not clear the external
2673
             * critical interrupt status
2674
             */
2675
#if 0
2676
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
2677
#endif
2678
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
2679
            return;
2680
        }
2681
    }
2682
    if (msr_ee != 0) {
2683
        /* Watchdog timer on embedded PowerPC */
2684
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
2685
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
2686
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
2687
            return;
2688
        }
2689
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
2690
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
2691
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
2692
            return;
2693
        }
2694
        /* Fixed interval timer on embedded PowerPC */
2695
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
2696
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
2697
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
2698
            return;
2699
        }
2700
        /* Programmable interval timer on embedded PowerPC */
2701
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
2702
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
2703
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
2704
            return;
2705
        }
2706
        /* Decrementer exception */
2707
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
2708
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
2709
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
2710
            return;
2711
        }
2712
        /* External interrupt */
2713
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
2714
            /* Taking an external interrupt does not clear the external
2715
             * interrupt status
2716
             */
2717
#if 0
2718
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
2719
#endif
2720
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
2721
            return;
2722
        }
2723
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
2724
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2725
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
2726
            return;
2727
        }
2728
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
2729
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
2730
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
2731
            return;
2732
        }
2733
        /* Thermal interrupt */
2734
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
2735
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
2736
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
2737
            return;
2738
        }
2739
    }
2740
}
2741
#endif /* !CONFIG_USER_ONLY */
2742

    
2743
void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2744
{
2745
    qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
2746
             TARGET_FMT_lx "\n", RA, msr);
2747
}
2748

    
2749
void cpu_reset(CPUPPCState *env)
2750
{
2751
    target_ulong msr;
2752

    
2753
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
2754
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
2755
        log_cpu_state(env, 0);
2756
    }
2757

    
2758
    msr = (target_ulong)0;
2759
    if (0) {
2760
        /* XXX: find a suitable condition to enable the hypervisor mode */
2761
        msr |= (target_ulong)MSR_HVB;
2762
    }
2763
    msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
2764
    msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
2765
    msr |= (target_ulong)1 << MSR_EP;
2766
#if defined (DO_SINGLE_STEP) && 0
2767
    /* Single step trace mode */
2768
    msr |= (target_ulong)1 << MSR_SE;
2769
    msr |= (target_ulong)1 << MSR_BE;
2770
#endif
2771
#if defined(CONFIG_USER_ONLY)
2772
    msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
2773
    msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
2774
    msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
2775
    msr |= (target_ulong)1 << MSR_PR;
2776
#else
2777
    env->excp_prefix = env->hreset_excp_prefix;
2778
    env->nip = env->hreset_vector | env->excp_prefix;
2779
    if (env->mmu_model != POWERPC_MMU_REAL)
2780
        ppc_tlb_invalidate_all(env);
2781
#endif
2782
    env->msr = msr & env->msr_mask;
2783
#if defined(TARGET_PPC64)
2784
    if (env->mmu_model & POWERPC_MMU_64)
2785
        env->msr |= (1ULL << MSR_SF);
2786
#endif
2787
    hreg_compute_hflags(env);
2788
    env->reserve_addr = (target_ulong)-1ULL;
2789
    /* Be sure no exception or interrupt is pending */
2790
    env->pending_interrupts = 0;
2791
    env->exception_index = POWERPC_EXCP_NONE;
2792
    env->error_code = 0;
2793
    /* Flush all TLBs */
2794
    tlb_flush(env, 1);
2795
}
2796

    
2797
CPUPPCState *cpu_ppc_init (const char *cpu_model)
2798
{
2799
    CPUPPCState *env;
2800
    const ppc_def_t *def;
2801

    
2802
    def = cpu_ppc_find_by_name(cpu_model);
2803
    if (!def)
2804
        return NULL;
2805

    
2806
    env = qemu_mallocz(sizeof(CPUPPCState));
2807
    cpu_exec_init(env);
2808
    ppc_translate_init();
2809
    env->cpu_model_str = cpu_model;
2810
    cpu_ppc_register_internal(env, def);
2811

    
2812
    qemu_init_vcpu(env);
2813

    
2814
    return env;
2815
}
2816

    
2817
void cpu_ppc_close (CPUPPCState *env)
2818
{
2819
    /* Should also remove all opcode tables... */
2820
    qemu_free(env);
2821
}