Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ a586e548

History | View | Annotate | Download (92.9 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
            /* XXX: there is a problem here or in the TLB fill code... */
1176
            ctx->prot = tlb->prot;
1177
            ctx->prot |= PAGE_EXEC;
1178
            ret = check_prot(ctx->prot, rw, access_type);
1179
            if (ret == -2)
1180
                env->spr[SPR_40x_ESR] = 0;
1181
            break;
1182
        }
1183
        if (ret >= 0) {
1184
            ctx->raddr = raddr;
1185
            LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1186
                      " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1187
                      ret);
1188
            return 0;
1189
        }
1190
    }
1191
    LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1192
              " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1193

    
1194
    return ret;
1195
}
1196

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

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

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

    
1249
    return ret;
1250
}
1251

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

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

    
1315
    return ret;
1316
}
1317

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

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

    
1386
    return ret;
1387
}
1388

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

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

    
1396
    return ctx.raddr & TARGET_PAGE_MASK;
1397
}
1398

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

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

    
1676
    return ret;
1677
}
1678

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2590
    if (msr_ile) {
2591
        new_msr |= (target_ulong)1 << MSR_LE;
2592
    }
2593

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

    
2626
    if (env->mmu_model == POWERPC_MMU_BOOKE) {
2627
        /* XXX: The BookE changes address space when switching modes,
2628
                we should probably implement that as different MMU indexes,
2629
                but for the moment we do it the slow way and flush all.  */
2630
        tlb_flush(env, 1);
2631
    }
2632
}
2633

    
2634
void do_interrupt (CPUState *env)
2635
{
2636
    powerpc_excp(env, env->excp_model, env->exception_index);
2637
}
2638

    
2639
void ppc_hw_interrupt (CPUPPCState *env)
2640
{
2641
    int hdice;
2642

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

    
2756
void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2757
{
2758
    qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
2759
             TARGET_FMT_lx "\n", RA, msr);
2760
}
2761

    
2762
void cpu_reset(CPUPPCState *env)
2763
{
2764
    target_ulong msr;
2765

    
2766
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
2767
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
2768
        log_cpu_state(env, 0);
2769
    }
2770

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

    
2810
CPUPPCState *cpu_ppc_init (const char *cpu_model)
2811
{
2812
    CPUPPCState *env;
2813
    const ppc_def_t *def;
2814

    
2815
    def = cpu_ppc_find_by_name(cpu_model);
2816
    if (!def)
2817
        return NULL;
2818

    
2819
    env = qemu_mallocz(sizeof(CPUPPCState));
2820
    cpu_exec_init(env);
2821
    ppc_translate_init();
2822
    env->cpu_model_str = cpu_model;
2823
    cpu_ppc_register_internal(env, def);
2824

    
2825
    qemu_init_vcpu(env);
2826

    
2827
    return env;
2828
}
2829

    
2830
void cpu_ppc_close (CPUPPCState *env)
2831
{
2832
    /* Should also remove all opcode tables... */
2833
    qemu_free(env);
2834
}