Statistics
| Branch: | Revision:

root / target-ppc / mmu_helper.c @ eb20c1c6

History | View | Annotate | Download (84.9 kB)

1
/*
2
 *  PowerPC MMU, TLB, SLB and BAT 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 "cpu.h"
20
#include "helper.h"
21
#include "sysemu/kvm.h"
22
#include "kvm_ppc.h"
23
#include "mmu-hash64.h"
24
#include "mmu-hash32.h"
25

    
26
//#define DEBUG_MMU
27
//#define DEBUG_BATS
28
//#define DEBUG_SOFTWARE_TLB
29
//#define DUMP_PAGE_TABLES
30
//#define DEBUG_SOFTWARE_TLB
31
//#define FLUSH_ALL_TLBS
32

    
33
#ifdef DEBUG_MMU
34
#  define LOG_MMU(...) qemu_log(__VA_ARGS__)
35
#  define LOG_MMU_STATE(env) log_cpu_state((env), 0)
36
#else
37
#  define LOG_MMU(...) do { } while (0)
38
#  define LOG_MMU_STATE(...) do { } while (0)
39
#endif
40

    
41
#ifdef DEBUG_SOFTWARE_TLB
42
#  define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
43
#else
44
#  define LOG_SWTLB(...) do { } while (0)
45
#endif
46

    
47
#ifdef DEBUG_BATS
48
#  define LOG_BATS(...) qemu_log(__VA_ARGS__)
49
#else
50
#  define LOG_BATS(...) do { } while (0)
51
#endif
52

    
53
/*****************************************************************************/
54
/* PowerPC MMU emulation */
55

    
56
/* Context used internally during MMU translations */
57
typedef struct mmu_ctx_t mmu_ctx_t;
58
struct mmu_ctx_t {
59
    hwaddr raddr;      /* Real address              */
60
    hwaddr eaddr;      /* Effective address         */
61
    int prot;                      /* Protection bits           */
62
    hwaddr hash[2];    /* Pagetable hash values     */
63
    target_ulong ptem;             /* Virtual segment ID | API  */
64
    int key;                       /* Access key                */
65
    int nx;                        /* Non-execute area          */
66
};
67

    
68
/* Common routines used by software and hardware TLBs emulation */
69
static inline int pte_is_valid(target_ulong pte0)
70
{
71
    return pte0 & 0x80000000 ? 1 : 0;
72
}
73

    
74
static inline void pte_invalidate(target_ulong *pte0)
75
{
76
    *pte0 &= ~0x80000000;
77
}
78

    
79
#define PTE_PTEM_MASK 0x7FFFFFBF
80
#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
81

    
82
static int pp_check(int key, int pp, int nx)
83
{
84
    int access;
85

    
86
    /* Compute access rights */
87
    access = 0;
88
    if (key == 0) {
89
        switch (pp) {
90
        case 0x0:
91
        case 0x1:
92
        case 0x2:
93
            access |= PAGE_WRITE;
94
            /* No break here */
95
        case 0x3:
96
            access |= PAGE_READ;
97
            break;
98
        }
99
    } else {
100
        switch (pp) {
101
        case 0x0:
102
            access = 0;
103
            break;
104
        case 0x1:
105
        case 0x3:
106
            access = PAGE_READ;
107
            break;
108
        case 0x2:
109
            access = PAGE_READ | PAGE_WRITE;
110
            break;
111
        }
112
    }
113
    if (nx == 0) {
114
        access |= PAGE_EXEC;
115
    }
116

    
117
    return access;
118
}
119

    
120
static int check_prot(int prot, int rw, int access_type)
121
{
122
    int ret;
123

    
124
    if (access_type == ACCESS_CODE) {
125
        if (prot & PAGE_EXEC) {
126
            ret = 0;
127
        } else {
128
            ret = -2;
129
        }
130
    } else if (rw) {
131
        if (prot & PAGE_WRITE) {
132
            ret = 0;
133
        } else {
134
            ret = -2;
135
        }
136
    } else {
137
        if (prot & PAGE_READ) {
138
            ret = 0;
139
        } else {
140
            ret = -2;
141
        }
142
    }
143

    
144
    return ret;
145
}
146

    
147
static inline int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
148
                                       target_ulong pte1, int h, int rw, int type)
149
{
150
    target_ulong ptem, mmask;
151
    int access, ret, pteh, ptev, pp;
152

    
153
    ret = -1;
154
    /* Check validity and table match */
155
    ptev = pte_is_valid(pte0);
156
    pteh = (pte0 >> 6) & 1;
157
    if (ptev && h == pteh) {
158
        /* Check vsid & api */
159
        ptem = pte0 & PTE_PTEM_MASK;
160
        mmask = PTE_CHECK_MASK;
161
        pp = pte1 & 0x00000003;
162
        if (ptem == ctx->ptem) {
163
            if (ctx->raddr != (hwaddr)-1ULL) {
164
                /* all matches should have equal RPN, WIMG & PP */
165
                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
166
                    qemu_log("Bad RPN/WIMG/PP\n");
167
                    return -3;
168
                }
169
            }
170
            /* Compute access rights */
171
            access = pp_check(ctx->key, pp, ctx->nx);
172
            /* Keep the matching PTE informations */
173
            ctx->raddr = pte1;
174
            ctx->prot = access;
175
            ret = check_prot(ctx->prot, rw, type);
176
            if (ret == 0) {
177
                /* Access granted */
178
                LOG_MMU("PTE access granted !\n");
179
            } else {
180
                /* Access right violation */
181
                LOG_MMU("PTE access rejected\n");
182
            }
183
        }
184
    }
185

    
186
    return ret;
187
}
188

    
189
static int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
190
                            int ret, int rw)
191
{
192
    int store = 0;
193

    
194
    /* Update page flags */
195
    if (!(*pte1p & 0x00000100)) {
196
        /* Update accessed flag */
197
        *pte1p |= 0x00000100;
198
        store = 1;
199
    }
200
    if (!(*pte1p & 0x00000080)) {
201
        if (rw == 1 && ret == 0) {
202
            /* Update changed flag */
203
            *pte1p |= 0x00000080;
204
            store = 1;
205
        } else {
206
            /* Force page fault for first write access */
207
            ctx->prot &= ~PAGE_WRITE;
208
        }
209
    }
210

    
211
    return store;
212
}
213

    
214
/* Software driven TLB helpers */
215
static inline int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
216
                                    int way, int is_code)
217
{
218
    int nr;
219

    
220
    /* Select TLB num in a way from address */
221
    nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
222
    /* Select TLB way */
223
    nr += env->tlb_per_way * way;
224
    /* 6xx have separate TLBs for instructions and data */
225
    if (is_code && env->id_tlbs == 1) {
226
        nr += env->nb_tlb;
227
    }
228

    
229
    return nr;
230
}
231

    
232
static inline void ppc6xx_tlb_invalidate_all(CPUPPCState *env)
233
{
234
    ppc6xx_tlb_t *tlb;
235
    int nr, max;
236

    
237
    /* LOG_SWTLB("Invalidate all TLBs\n"); */
238
    /* Invalidate all defined software TLB */
239
    max = env->nb_tlb;
240
    if (env->id_tlbs == 1) {
241
        max *= 2;
242
    }
243
    for (nr = 0; nr < max; nr++) {
244
        tlb = &env->tlb.tlb6[nr];
245
        pte_invalidate(&tlb->pte0);
246
    }
247
    tlb_flush(env, 1);
248
}
249

    
250
static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState *env,
251
                                               target_ulong eaddr,
252
                                               int is_code, int match_epn)
253
{
254
#if !defined(FLUSH_ALL_TLBS)
255
    ppc6xx_tlb_t *tlb;
256
    int way, nr;
257

    
258
    /* Invalidate ITLB + DTLB, all ways */
259
    for (way = 0; way < env->nb_ways; way++) {
260
        nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
261
        tlb = &env->tlb.tlb6[nr];
262
        if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
263
            LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
264
                      env->nb_tlb, eaddr);
265
            pte_invalidate(&tlb->pte0);
266
            tlb_flush_page(env, tlb->EPN);
267
        }
268
    }
269
#else
270
    /* XXX: PowerPC specification say this is valid as well */
271
    ppc6xx_tlb_invalidate_all(env);
272
#endif
273
}
274

    
275
static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState *env,
276
                                              target_ulong eaddr, int is_code)
277
{
278
    ppc6xx_tlb_invalidate_virt2(env, eaddr, is_code, 0);
279
}
280

    
281
static void ppc6xx_tlb_store(CPUPPCState *env, target_ulong EPN, int way,
282
                             int is_code, target_ulong pte0, target_ulong pte1)
283
{
284
    ppc6xx_tlb_t *tlb;
285
    int nr;
286

    
287
    nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
288
    tlb = &env->tlb.tlb6[nr];
289
    LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
290
              " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
291
    /* Invalidate any pending reference in QEMU for this virtual address */
292
    ppc6xx_tlb_invalidate_virt2(env, EPN, is_code, 1);
293
    tlb->pte0 = pte0;
294
    tlb->pte1 = pte1;
295
    tlb->EPN = EPN;
296
    /* Store last way for LRU mechanism */
297
    env->last_way = way;
298
}
299

    
300
static inline int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
301
                                   target_ulong eaddr, int rw, int access_type)
302
{
303
    ppc6xx_tlb_t *tlb;
304
    int nr, best, way;
305
    int ret;
306

    
307
    best = -1;
308
    ret = -1; /* No TLB found */
309
    for (way = 0; way < env->nb_ways; way++) {
310
        nr = ppc6xx_tlb_getnum(env, eaddr, way,
311
                               access_type == ACCESS_CODE ? 1 : 0);
312
        tlb = &env->tlb.tlb6[nr];
313
        /* This test "emulates" the PTE index match for hardware TLBs */
314
        if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
315
            LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
316
                      "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb,
317
                      pte_is_valid(tlb->pte0) ? "valid" : "inval",
318
                      tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
319
            continue;
320
        }
321
        LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " "
322
                  TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb,
323
                  pte_is_valid(tlb->pte0) ? "valid" : "inval",
324
                  tlb->EPN, eaddr, tlb->pte1,
325
                  rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
326
        switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
327
        case -3:
328
            /* TLB inconsistency */
329
            return -1;
330
        case -2:
331
            /* Access violation */
332
            ret = -2;
333
            best = nr;
334
            break;
335
        case -1:
336
        default:
337
            /* No match */
338
            break;
339
        case 0:
340
            /* access granted */
341
            /* XXX: we should go on looping to check all TLBs consistency
342
             *      but we can speed-up the whole thing as the
343
             *      result would be undefined if TLBs are not consistent.
344
             */
345
            ret = 0;
346
            best = nr;
347
            goto done;
348
        }
349
    }
350
    if (best != -1) {
351
    done:
352
        LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
353
                  ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
354
        /* Update page flags */
355
        pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, rw);
356
    }
357

    
358
    return ret;
359
}
360

    
361
/* Perform BAT hit & translation */
362
static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp,
363
                                 int *validp, int *protp, target_ulong *BATu,
364
                                 target_ulong *BATl)
365
{
366
    target_ulong bl;
367
    int pp, valid, prot;
368

    
369
    bl = (*BATu & 0x00001FFC) << 15;
370
    valid = 0;
371
    prot = 0;
372
    if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
373
        ((msr_pr != 0) && (*BATu & 0x00000001))) {
374
        valid = 1;
375
        pp = *BATl & 0x00000003;
376
        if (pp != 0) {
377
            prot = PAGE_READ | PAGE_EXEC;
378
            if (pp == 0x2) {
379
                prot |= PAGE_WRITE;
380
            }
381
        }
382
    }
383
    *blp = bl;
384
    *validp = valid;
385
    *protp = prot;
386
}
387

    
388
static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
389
                           target_ulong virtual, int rw, int type)
390
{
391
    target_ulong *BATlt, *BATut, *BATu, *BATl;
392
    target_ulong BEPIl, BEPIu, bl;
393
    int i, valid, prot;
394
    int ret = -1;
395

    
396
    LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
397
             type == ACCESS_CODE ? 'I' : 'D', virtual);
398
    switch (type) {
399
    case ACCESS_CODE:
400
        BATlt = env->IBAT[1];
401
        BATut = env->IBAT[0];
402
        break;
403
    default:
404
        BATlt = env->DBAT[1];
405
        BATut = env->DBAT[0];
406
        break;
407
    }
408
    for (i = 0; i < env->nb_BATs; i++) {
409
        BATu = &BATut[i];
410
        BATl = &BATlt[i];
411
        BEPIu = *BATu & 0xF0000000;
412
        BEPIl = *BATu & 0x0FFE0000;
413
        bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
414
        LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
415
                 " BATl " TARGET_FMT_lx "\n", __func__,
416
                 type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
417
        if ((virtual & 0xF0000000) == BEPIu &&
418
            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
419
            /* BAT matches */
420
            if (valid != 0) {
421
                /* Get physical address */
422
                ctx->raddr = (*BATl & 0xF0000000) |
423
                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
424
                    (virtual & 0x0001F000);
425
                /* Compute access rights */
426
                ctx->prot = prot;
427
                ret = check_prot(ctx->prot, rw, type);
428
                if (ret == 0) {
429
                    LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
430
                             i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
431
                             ctx->prot & PAGE_WRITE ? 'W' : '-');
432
                }
433
                break;
434
            }
435
        }
436
    }
437
    if (ret < 0) {
438
#if defined(DEBUG_BATS)
439
        if (qemu_log_enabled()) {
440
            LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
441
            for (i = 0; i < 4; i++) {
442
                BATu = &BATut[i];
443
                BATl = &BATlt[i];
444
                BEPIu = *BATu & 0xF0000000;
445
                BEPIl = *BATu & 0x0FFE0000;
446
                bl = (*BATu & 0x00001FFC) << 15;
447
                LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
448
                         " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
449
                         TARGET_FMT_lx " " TARGET_FMT_lx "\n",
450
                         __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
451
                         *BATu, *BATl, BEPIu, BEPIl, bl);
452
            }
453
        }
454
#endif
455
    }
456
    /* No hit */
457
    return ret;
458
}
459

    
460
/* Perform segment based translation */
461
static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
462
                                      target_ulong eaddr, int rw, int type)
463
{
464
    hwaddr hash;
465
    target_ulong vsid;
466
    int ds, pr, target_page_bits;
467
    int ret;
468
    target_ulong sr, pgidx;
469

    
470
    pr = msr_pr;
471
    ctx->eaddr = eaddr;
472

    
473
    sr = env->sr[eaddr >> 28];
474
    ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
475
                ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
476
    ds = sr & 0x80000000 ? 1 : 0;
477
    ctx->nx = sr & 0x10000000 ? 1 : 0;
478
    vsid = sr & 0x00FFFFFF;
479
    target_page_bits = TARGET_PAGE_BITS;
480
    LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
481
            TARGET_FMT_lx " lr=" TARGET_FMT_lx
482
            " ir=%d dr=%d pr=%d %d t=%d\n",
483
            eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
484
            (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
485
    pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
486
    hash = vsid ^ pgidx;
487
    ctx->ptem = (vsid << 7) | (pgidx >> 10);
488

    
489
    LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
490
            ctx->key, ds, ctx->nx, vsid);
491
    ret = -1;
492
    if (!ds) {
493
        /* Check if instruction fetch is allowed, if needed */
494
        if (type != ACCESS_CODE || ctx->nx == 0) {
495
            /* Page address translation */
496
            LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
497
                    " hash " TARGET_FMT_plx "\n",
498
                    env->htab_base, env->htab_mask, hash);
499
            ctx->hash[0] = hash;
500
            ctx->hash[1] = ~hash;
501

    
502
            /* Initialize real address with an invalid value */
503
            ctx->raddr = (hwaddr)-1ULL;
504
            /* Software TLB search */
505
            ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
506
#if defined(DUMP_PAGE_TABLES)
507
            if (qemu_log_enabled()) {
508
                hwaddr curaddr;
509
                uint32_t a0, a1, a2, a3;
510

    
511
                qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
512
                         "\n", sdr, mask + 0x80);
513
                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
514
                     curaddr += 16) {
515
                    a0 = ldl_phys(curaddr);
516
                    a1 = ldl_phys(curaddr + 4);
517
                    a2 = ldl_phys(curaddr + 8);
518
                    a3 = ldl_phys(curaddr + 12);
519
                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
520
                        qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
521
                                 curaddr, a0, a1, a2, a3);
522
                    }
523
                }
524
            }
525
#endif
526
        } else {
527
            LOG_MMU("No access allowed\n");
528
            ret = -3;
529
        }
530
    } else {
531
        target_ulong sr;
532

    
533
        LOG_MMU("direct store...\n");
534
        /* Direct-store segment : absolutely *BUGGY* for now */
535

    
536
        /* Direct-store implies a 32-bit MMU.
537
         * Check the Segment Register's bus unit ID (BUID).
538
         */
539
        sr = env->sr[eaddr >> 28];
540
        if ((sr & 0x1FF00000) >> 20 == 0x07f) {
541
            /* Memory-forced I/O controller interface access */
542
            /* If T=1 and BUID=x'07F', the 601 performs a memory access
543
             * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
544
             */
545
            ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
546
            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
547
            return 0;
548
        }
549

    
550
        switch (type) {
551
        case ACCESS_INT:
552
            /* Integer load/store : only access allowed */
553
            break;
554
        case ACCESS_CODE:
555
            /* No code fetch is allowed in direct-store areas */
556
            return -4;
557
        case ACCESS_FLOAT:
558
            /* Floating point load/store */
559
            return -4;
560
        case ACCESS_RES:
561
            /* lwarx, ldarx or srwcx. */
562
            return -4;
563
        case ACCESS_CACHE:
564
            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
565
            /* Should make the instruction do no-op.
566
             * As it already do no-op, it's quite easy :-)
567
             */
568
            ctx->raddr = eaddr;
569
            return 0;
570
        case ACCESS_EXT:
571
            /* eciwx or ecowx */
572
            return -4;
573
        default:
574
            qemu_log("ERROR: instruction should not need "
575
                        "address translation\n");
576
            return -4;
577
        }
578
        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
579
            ctx->raddr = eaddr;
580
            ret = 2;
581
        } else {
582
            ret = -2;
583
        }
584
    }
585

    
586
    return ret;
587
}
588

    
589
/* Generic TLB check function for embedded PowerPC implementations */
590
static int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
591
                            hwaddr *raddrp,
592
                            target_ulong address, uint32_t pid, int ext,
593
                            int i)
594
{
595
    target_ulong mask;
596

    
597
    /* Check valid flag */
598
    if (!(tlb->prot & PAGE_VALID)) {
599
        return -1;
600
    }
601
    mask = ~(tlb->size - 1);
602
    LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
603
              " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
604
              mask, (uint32_t)tlb->PID, tlb->prot);
605
    /* Check PID */
606
    if (tlb->PID != 0 && tlb->PID != pid) {
607
        return -1;
608
    }
609
    /* Check effective address */
610
    if ((address & mask) != tlb->EPN) {
611
        return -1;
612
    }
613
    *raddrp = (tlb->RPN & mask) | (address & ~mask);
614
    if (ext) {
615
        /* Extend the physical address to 36 bits */
616
        *raddrp |= (uint64_t)(tlb->RPN & 0xF) << 32;
617
    }
618

    
619
    return 0;
620
}
621

    
622
/* Generic TLB search function for PowerPC embedded implementations */
623
static int ppcemb_tlb_search(CPUPPCState *env, target_ulong address,
624
                             uint32_t pid)
625
{
626
    ppcemb_tlb_t *tlb;
627
    hwaddr raddr;
628
    int i, ret;
629

    
630
    /* Default return value is no match */
631
    ret = -1;
632
    for (i = 0; i < env->nb_tlb; i++) {
633
        tlb = &env->tlb.tlbe[i];
634
        if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
635
            ret = i;
636
            break;
637
        }
638
    }
639

    
640
    return ret;
641
}
642

    
643
/* Helpers specific to PowerPC 40x implementations */
644
static inline void ppc4xx_tlb_invalidate_all(CPUPPCState *env)
645
{
646
    ppcemb_tlb_t *tlb;
647
    int i;
648

    
649
    for (i = 0; i < env->nb_tlb; i++) {
650
        tlb = &env->tlb.tlbe[i];
651
        tlb->prot &= ~PAGE_VALID;
652
    }
653
    tlb_flush(env, 1);
654
}
655

    
656
static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState *env,
657
                                              target_ulong eaddr, uint32_t pid)
658
{
659
#if !defined(FLUSH_ALL_TLBS)
660
    ppcemb_tlb_t *tlb;
661
    hwaddr raddr;
662
    target_ulong page, end;
663
    int i;
664

    
665
    for (i = 0; i < env->nb_tlb; i++) {
666
        tlb = &env->tlb.tlbe[i];
667
        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
668
            end = tlb->EPN + tlb->size;
669
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
670
                tlb_flush_page(env, page);
671
            }
672
            tlb->prot &= ~PAGE_VALID;
673
            break;
674
        }
675
    }
676
#else
677
    ppc4xx_tlb_invalidate_all(env);
678
#endif
679
}
680

    
681
static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
682
                                       target_ulong address, int rw,
683
                                       int access_type)
684
{
685
    ppcemb_tlb_t *tlb;
686
    hwaddr raddr;
687
    int i, ret, zsel, zpr, pr;
688

    
689
    ret = -1;
690
    raddr = (hwaddr)-1ULL;
691
    pr = msr_pr;
692
    for (i = 0; i < env->nb_tlb; i++) {
693
        tlb = &env->tlb.tlbe[i];
694
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
695
                             env->spr[SPR_40x_PID], 0, i) < 0) {
696
            continue;
697
        }
698
        zsel = (tlb->attr >> 4) & 0xF;
699
        zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
700
        LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
701
                    __func__, i, zsel, zpr, rw, tlb->attr);
702
        /* Check execute enable bit */
703
        switch (zpr) {
704
        case 0x2:
705
            if (pr != 0) {
706
                goto check_perms;
707
            }
708
            /* No break here */
709
        case 0x3:
710
            /* All accesses granted */
711
            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
712
            ret = 0;
713
            break;
714
        case 0x0:
715
            if (pr != 0) {
716
                /* Raise Zone protection fault.  */
717
                env->spr[SPR_40x_ESR] = 1 << 22;
718
                ctx->prot = 0;
719
                ret = -2;
720
                break;
721
            }
722
            /* No break here */
723
        case 0x1:
724
        check_perms:
725
            /* Check from TLB entry */
726
            ctx->prot = tlb->prot;
727
            ret = check_prot(ctx->prot, rw, access_type);
728
            if (ret == -2) {
729
                env->spr[SPR_40x_ESR] = 0;
730
            }
731
            break;
732
        }
733
        if (ret >= 0) {
734
            ctx->raddr = raddr;
735
            LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
736
                      " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
737
                      ret);
738
            return 0;
739
        }
740
    }
741
    LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
742
              " %d %d\n", __func__, address, raddr, ctx->prot, ret);
743

    
744
    return ret;
745
}
746

    
747
void store_40x_sler(CPUPPCState *env, uint32_t val)
748
{
749
    /* XXX: TO BE FIXED */
750
    if (val != 0x00000000) {
751
        cpu_abort(env, "Little-endian regions are not supported by now\n");
752
    }
753
    env->spr[SPR_405_SLER] = val;
754
}
755

    
756
static inline int mmubooke_check_tlb(CPUPPCState *env, ppcemb_tlb_t *tlb,
757
                                     hwaddr *raddr, int *prot,
758
                                     target_ulong address, int rw,
759
                                     int access_type, int i)
760
{
761
    int ret, prot2;
762

    
763
    if (ppcemb_tlb_check(env, tlb, raddr, address,
764
                         env->spr[SPR_BOOKE_PID],
765
                         !env->nb_pids, i) >= 0) {
766
        goto found_tlb;
767
    }
768

    
769
    if (env->spr[SPR_BOOKE_PID1] &&
770
        ppcemb_tlb_check(env, tlb, raddr, address,
771
                         env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
772
        goto found_tlb;
773
    }
774

    
775
    if (env->spr[SPR_BOOKE_PID2] &&
776
        ppcemb_tlb_check(env, tlb, raddr, address,
777
                         env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
778
        goto found_tlb;
779
    }
780

    
781
    LOG_SWTLB("%s: TLB entry not found\n", __func__);
782
    return -1;
783

    
784
found_tlb:
785

    
786
    if (msr_pr != 0) {
787
        prot2 = tlb->prot & 0xF;
788
    } else {
789
        prot2 = (tlb->prot >> 4) & 0xF;
790
    }
791

    
792
    /* Check the address space */
793
    if (access_type == ACCESS_CODE) {
794
        if (msr_ir != (tlb->attr & 1)) {
795
            LOG_SWTLB("%s: AS doesn't match\n", __func__);
796
            return -1;
797
        }
798

    
799
        *prot = prot2;
800
        if (prot2 & PAGE_EXEC) {
801
            LOG_SWTLB("%s: good TLB!\n", __func__);
802
            return 0;
803
        }
804

    
805
        LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, prot2);
806
        ret = -3;
807
    } else {
808
        if (msr_dr != (tlb->attr & 1)) {
809
            LOG_SWTLB("%s: AS doesn't match\n", __func__);
810
            return -1;
811
        }
812

    
813
        *prot = prot2;
814
        if ((!rw && prot2 & PAGE_READ) || (rw && (prot2 & PAGE_WRITE))) {
815
            LOG_SWTLB("%s: found TLB!\n", __func__);
816
            return 0;
817
        }
818

    
819
        LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, prot2);
820
        ret = -2;
821
    }
822

    
823
    return ret;
824
}
825

    
826
static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
827
                                         target_ulong address, int rw,
828
                                         int access_type)
829
{
830
    ppcemb_tlb_t *tlb;
831
    hwaddr raddr;
832
    int i, ret;
833

    
834
    ret = -1;
835
    raddr = (hwaddr)-1ULL;
836
    for (i = 0; i < env->nb_tlb; i++) {
837
        tlb = &env->tlb.tlbe[i];
838
        ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
839
                                 access_type, i);
840
        if (!ret) {
841
            break;
842
        }
843
    }
844

    
845
    if (ret >= 0) {
846
        ctx->raddr = raddr;
847
        LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
848
                  " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
849
                  ret);
850
    } else {
851
        LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
852
                  " %d %d\n", __func__, address, raddr, ctx->prot, ret);
853
    }
854

    
855
    return ret;
856
}
857

    
858
static void booke206_flush_tlb(CPUPPCState *env, int flags,
859
                               const int check_iprot)
860
{
861
    int tlb_size;
862
    int i, j;
863
    ppcmas_tlb_t *tlb = env->tlb.tlbm;
864

    
865
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
866
        if (flags & (1 << i)) {
867
            tlb_size = booke206_tlb_size(env, i);
868
            for (j = 0; j < tlb_size; j++) {
869
                if (!check_iprot || !(tlb[j].mas1 & MAS1_IPROT)) {
870
                    tlb[j].mas1 &= ~MAS1_VALID;
871
                }
872
            }
873
        }
874
        tlb += booke206_tlb_size(env, i);
875
    }
876

    
877
    tlb_flush(env, 1);
878
}
879

    
880
static hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
881
                                        ppcmas_tlb_t *tlb)
882
{
883
    int tlbm_size;
884

    
885
    tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
886

    
887
    return 1024ULL << tlbm_size;
888
}
889

    
890
/* TLB check function for MAS based SoftTLBs */
891
static int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
892
                            hwaddr *raddrp,
893
                     target_ulong address, uint32_t pid)
894
{
895
    target_ulong mask;
896
    uint32_t tlb_pid;
897

    
898
    /* Check valid flag */
899
    if (!(tlb->mas1 & MAS1_VALID)) {
900
        return -1;
901
    }
902

    
903
    mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
904
    LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%"
905
              PRIx64 " mask=0x" TARGET_FMT_lx " MAS7_3=0x%" PRIx64 " MAS8=%x\n",
906
              __func__, address, pid, tlb->mas1, tlb->mas2, mask, tlb->mas7_3,
907
              tlb->mas8);
908

    
909
    /* Check PID */
910
    tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
911
    if (tlb_pid != 0 && tlb_pid != pid) {
912
        return -1;
913
    }
914

    
915
    /* Check effective address */
916
    if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
917
        return -1;
918
    }
919

    
920
    if (raddrp) {
921
        *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
922
    }
923

    
924
    return 0;
925
}
926

    
927
static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb,
928
                                 hwaddr *raddr, int *prot,
929
                                 target_ulong address, int rw,
930
                                 int access_type)
931
{
932
    int ret;
933
    int prot2 = 0;
934

    
935
    if (ppcmas_tlb_check(env, tlb, raddr, address,
936
                         env->spr[SPR_BOOKE_PID]) >= 0) {
937
        goto found_tlb;
938
    }
939

    
940
    if (env->spr[SPR_BOOKE_PID1] &&
941
        ppcmas_tlb_check(env, tlb, raddr, address,
942
                         env->spr[SPR_BOOKE_PID1]) >= 0) {
943
        goto found_tlb;
944
    }
945

    
946
    if (env->spr[SPR_BOOKE_PID2] &&
947
        ppcmas_tlb_check(env, tlb, raddr, address,
948
                         env->spr[SPR_BOOKE_PID2]) >= 0) {
949
        goto found_tlb;
950
    }
951

    
952
    LOG_SWTLB("%s: TLB entry not found\n", __func__);
953
    return -1;
954

    
955
found_tlb:
956

    
957
    if (msr_pr != 0) {
958
        if (tlb->mas7_3 & MAS3_UR) {
959
            prot2 |= PAGE_READ;
960
        }
961
        if (tlb->mas7_3 & MAS3_UW) {
962
            prot2 |= PAGE_WRITE;
963
        }
964
        if (tlb->mas7_3 & MAS3_UX) {
965
            prot2 |= PAGE_EXEC;
966
        }
967
    } else {
968
        if (tlb->mas7_3 & MAS3_SR) {
969
            prot2 |= PAGE_READ;
970
        }
971
        if (tlb->mas7_3 & MAS3_SW) {
972
            prot2 |= PAGE_WRITE;
973
        }
974
        if (tlb->mas7_3 & MAS3_SX) {
975
            prot2 |= PAGE_EXEC;
976
        }
977
    }
978

    
979
    /* Check the address space and permissions */
980
    if (access_type == ACCESS_CODE) {
981
        if (msr_ir != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
982
            LOG_SWTLB("%s: AS doesn't match\n", __func__);
983
            return -1;
984
        }
985

    
986
        *prot = prot2;
987
        if (prot2 & PAGE_EXEC) {
988
            LOG_SWTLB("%s: good TLB!\n", __func__);
989
            return 0;
990
        }
991

    
992
        LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, prot2);
993
        ret = -3;
994
    } else {
995
        if (msr_dr != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
996
            LOG_SWTLB("%s: AS doesn't match\n", __func__);
997
            return -1;
998
        }
999

    
1000
        *prot = prot2;
1001
        if ((!rw && prot2 & PAGE_READ) || (rw && (prot2 & PAGE_WRITE))) {
1002
            LOG_SWTLB("%s: found TLB!\n", __func__);
1003
            return 0;
1004
        }
1005

    
1006
        LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, prot2);
1007
        ret = -2;
1008
    }
1009

    
1010
    return ret;
1011
}
1012

    
1013
static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
1014
                                            target_ulong address, int rw,
1015
                                            int access_type)
1016
{
1017
    ppcmas_tlb_t *tlb;
1018
    hwaddr raddr;
1019
    int i, j, ret;
1020

    
1021
    ret = -1;
1022
    raddr = (hwaddr)-1ULL;
1023

    
1024
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1025
        int ways = booke206_tlb_ways(env, i);
1026

    
1027
        for (j = 0; j < ways; j++) {
1028
            tlb = booke206_get_tlbm(env, i, address, j);
1029
            if (!tlb) {
1030
                continue;
1031
            }
1032
            ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
1033
                                        rw, access_type);
1034
            if (ret != -1) {
1035
                goto found_tlb;
1036
            }
1037
        }
1038
    }
1039

    
1040
found_tlb:
1041

    
1042
    if (ret >= 0) {
1043
        ctx->raddr = raddr;
1044
        LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1045
                  " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1046
                  ret);
1047
    } else {
1048
        LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1049
                  " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1050
    }
1051

    
1052
    return ret;
1053
}
1054

    
1055
static const char *book3e_tsize_to_str[32] = {
1056
    "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1057
    "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1058
    "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1059
    "1T", "2T"
1060
};
1061

    
1062
static void mmubooke_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
1063
                                 CPUPPCState *env)
1064
{
1065
    ppcemb_tlb_t *entry;
1066
    int i;
1067

    
1068
    if (kvm_enabled() && !env->kvm_sw_tlb) {
1069
        cpu_fprintf(f, "Cannot access KVM TLB\n");
1070
        return;
1071
    }
1072

    
1073
    cpu_fprintf(f, "\nTLB:\n");
1074
    cpu_fprintf(f, "Effective          Physical           Size PID   Prot     "
1075
                "Attr\n");
1076

    
1077
    entry = &env->tlb.tlbe[0];
1078
    for (i = 0; i < env->nb_tlb; i++, entry++) {
1079
        hwaddr ea, pa;
1080
        target_ulong mask;
1081
        uint64_t size = (uint64_t)entry->size;
1082
        char size_buf[20];
1083

    
1084
        /* Check valid flag */
1085
        if (!(entry->prot & PAGE_VALID)) {
1086
            continue;
1087
        }
1088

    
1089
        mask = ~(entry->size - 1);
1090
        ea = entry->EPN & mask;
1091
        pa = entry->RPN & mask;
1092
        /* Extend the physical address to 36 bits */
1093
        pa |= (hwaddr)(entry->RPN & 0xF) << 32;
1094
        size /= 1024;
1095
        if (size >= 1024) {
1096
            snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / 1024);
1097
        } else {
1098
            snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size);
1099
        }
1100
        cpu_fprintf(f, "0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n",
1101
                    (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID,
1102
                    entry->prot, entry->attr);
1103
    }
1104

    
1105
}
1106

    
1107
static void mmubooke206_dump_one_tlb(FILE *f, fprintf_function cpu_fprintf,
1108
                                     CPUPPCState *env, int tlbn, int offset,
1109
                                     int tlbsize)
1110
{
1111
    ppcmas_tlb_t *entry;
1112
    int i;
1113

    
1114
    cpu_fprintf(f, "\nTLB%d:\n", tlbn);
1115
    cpu_fprintf(f, "Effective          Physical           Size TID   TS SRWX"
1116
                " URWX WIMGE U0123\n");
1117

    
1118
    entry = &env->tlb.tlbm[offset];
1119
    for (i = 0; i < tlbsize; i++, entry++) {
1120
        hwaddr ea, pa, size;
1121
        int tsize;
1122

    
1123
        if (!(entry->mas1 & MAS1_VALID)) {
1124
            continue;
1125
        }
1126

    
1127
        tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1128
        size = 1024ULL << tsize;
1129
        ea = entry->mas2 & ~(size - 1);
1130
        pa = entry->mas7_3 & ~(size - 1);
1131

    
1132
        cpu_fprintf(f, "0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u  S%c%c%c"
1133
                    "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1134
                    (uint64_t)ea, (uint64_t)pa,
1135
                    book3e_tsize_to_str[tsize],
1136
                    (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
1137
                    (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
1138
                    entry->mas7_3 & MAS3_SR ? 'R' : '-',
1139
                    entry->mas7_3 & MAS3_SW ? 'W' : '-',
1140
                    entry->mas7_3 & MAS3_SX ? 'X' : '-',
1141
                    entry->mas7_3 & MAS3_UR ? 'R' : '-',
1142
                    entry->mas7_3 & MAS3_UW ? 'W' : '-',
1143
                    entry->mas7_3 & MAS3_UX ? 'X' : '-',
1144
                    entry->mas2 & MAS2_W ? 'W' : '-',
1145
                    entry->mas2 & MAS2_I ? 'I' : '-',
1146
                    entry->mas2 & MAS2_M ? 'M' : '-',
1147
                    entry->mas2 & MAS2_G ? 'G' : '-',
1148
                    entry->mas2 & MAS2_E ? 'E' : '-',
1149
                    entry->mas7_3 & MAS3_U0 ? '0' : '-',
1150
                    entry->mas7_3 & MAS3_U1 ? '1' : '-',
1151
                    entry->mas7_3 & MAS3_U2 ? '2' : '-',
1152
                    entry->mas7_3 & MAS3_U3 ? '3' : '-');
1153
    }
1154
}
1155

    
1156
static void mmubooke206_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
1157
                                 CPUPPCState *env)
1158
{
1159
    int offset = 0;
1160
    int i;
1161

    
1162
    if (kvm_enabled() && !env->kvm_sw_tlb) {
1163
        cpu_fprintf(f, "Cannot access KVM TLB\n");
1164
        return;
1165
    }
1166

    
1167
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1168
        int size = booke206_tlb_size(env, i);
1169

    
1170
        if (size == 0) {
1171
            continue;
1172
        }
1173

    
1174
        mmubooke206_dump_one_tlb(f, cpu_fprintf, env, i, offset, size);
1175
        offset += size;
1176
    }
1177
}
1178

    
1179
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
1180
{
1181
    switch (env->mmu_model) {
1182
    case POWERPC_MMU_BOOKE:
1183
        mmubooke_dump_mmu(f, cpu_fprintf, env);
1184
        break;
1185
    case POWERPC_MMU_BOOKE206:
1186
        mmubooke206_dump_mmu(f, cpu_fprintf, env);
1187
        break;
1188
#if defined(TARGET_PPC64)
1189
    case POWERPC_MMU_64B:
1190
    case POWERPC_MMU_2_06:
1191
    case POWERPC_MMU_2_06d:
1192
        dump_slb(f, cpu_fprintf, env);
1193
        break;
1194
#endif
1195
    default:
1196
        qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
1197
    }
1198
}
1199

    
1200
static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
1201
                                 target_ulong eaddr, int rw)
1202
{
1203
    int in_plb, ret;
1204

    
1205
    ctx->raddr = eaddr;
1206
    ctx->prot = PAGE_READ | PAGE_EXEC;
1207
    ret = 0;
1208
    switch (env->mmu_model) {
1209
    case POWERPC_MMU_SOFT_6xx:
1210
    case POWERPC_MMU_SOFT_74xx:
1211
    case POWERPC_MMU_SOFT_4xx:
1212
    case POWERPC_MMU_REAL:
1213
    case POWERPC_MMU_BOOKE:
1214
        ctx->prot |= PAGE_WRITE;
1215
        break;
1216

    
1217
    case POWERPC_MMU_SOFT_4xx_Z:
1218
        if (unlikely(msr_pe != 0)) {
1219
            /* 403 family add some particular protections,
1220
             * using PBL/PBU registers for accesses with no translation.
1221
             */
1222
            in_plb =
1223
                /* Check PLB validity */
1224
                (env->pb[0] < env->pb[1] &&
1225
                 /* and address in plb area */
1226
                 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1227
                (env->pb[2] < env->pb[3] &&
1228
                 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1229
            if (in_plb ^ msr_px) {
1230
                /* Access in protected area */
1231
                if (rw == 1) {
1232
                    /* Access is not allowed */
1233
                    ret = -2;
1234
                }
1235
            } else {
1236
                /* Read-write access is allowed */
1237
                ctx->prot |= PAGE_WRITE;
1238
            }
1239
        }
1240
        break;
1241

    
1242
    default:
1243
        /* Caller's checks mean we should never get here for other models */
1244
        abort();
1245
        return -1;
1246
    }
1247

    
1248
    return ret;
1249
}
1250

    
1251
static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
1252
                                target_ulong eaddr, int rw, int access_type)
1253
{
1254
    int ret = -1;
1255
    bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
1256
        || (access_type != ACCESS_CODE && msr_dr == 0);
1257

    
1258
#if 0
1259
    qemu_log("%s\n", __func__);
1260
#endif
1261

    
1262
    switch (env->mmu_model) {
1263
    case POWERPC_MMU_SOFT_6xx:
1264
    case POWERPC_MMU_SOFT_74xx:
1265
        if (real_mode) {
1266
            ret = check_physical(env, ctx, eaddr, rw);
1267
        } else {
1268
            /* Try to find a BAT */
1269
            if (env->nb_BATs != 0) {
1270
                ret = get_bat_6xx_tlb(env, ctx, eaddr, rw, access_type);
1271
            }
1272
            if (ret < 0) {
1273
                /* We didn't match any BAT entry or don't have BATs */
1274
                ret = get_segment_6xx_tlb(env, ctx, eaddr, rw, access_type);
1275
            }
1276
        }
1277
        break;
1278

    
1279
    case POWERPC_MMU_SOFT_4xx:
1280
    case POWERPC_MMU_SOFT_4xx_Z:
1281
        if (real_mode) {
1282
            ret = check_physical(env, ctx, eaddr, rw);
1283
        } else {
1284
            ret = mmu40x_get_physical_address(env, ctx, eaddr,
1285
                                              rw, access_type);
1286
        }
1287
        break;
1288
    case POWERPC_MMU_BOOKE:
1289
        ret = mmubooke_get_physical_address(env, ctx, eaddr,
1290
                                            rw, access_type);
1291
        break;
1292
    case POWERPC_MMU_BOOKE206:
1293
        ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1294
                                               access_type);
1295
        break;
1296
    case POWERPC_MMU_MPC8xx:
1297
        /* XXX: TODO */
1298
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1299
        break;
1300
    case POWERPC_MMU_REAL:
1301
        if (real_mode) {
1302
            ret = check_physical(env, ctx, eaddr, rw);
1303
        } else {
1304
            cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1305
        }
1306
        return -1;
1307
    default:
1308
        cpu_abort(env, "Unknown or invalid MMU model\n");
1309
        return -1;
1310
    }
1311
#if 0
1312
    qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1313
             __func__, eaddr, ret, ctx->raddr);
1314
#endif
1315

    
1316
    return ret;
1317
}
1318

    
1319
hwaddr cpu_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
1320
{
1321
    mmu_ctx_t ctx;
1322

    
1323
    switch (env->mmu_model) {
1324
#if defined(TARGET_PPC64)
1325
    case POWERPC_MMU_64B:
1326
    case POWERPC_MMU_2_06:
1327
    case POWERPC_MMU_2_06d:
1328
        return ppc_hash64_get_phys_page_debug(env, addr);
1329
#endif
1330

    
1331
    case POWERPC_MMU_32B:
1332
    case POWERPC_MMU_601:
1333
        return ppc_hash32_get_phys_page_debug(env, addr);
1334

    
1335
    default:
1336
        ;
1337
    }
1338

    
1339
    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0)) {
1340
        return -1;
1341
    }
1342

    
1343
    return ctx.raddr & TARGET_PAGE_MASK;
1344
}
1345

    
1346
static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
1347
                                     int rw)
1348
{
1349
    env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1350
    env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1351
    env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1352
    env->spr[SPR_BOOKE_MAS3] = 0;
1353
    env->spr[SPR_BOOKE_MAS6] = 0;
1354
    env->spr[SPR_BOOKE_MAS7] = 0;
1355

    
1356
    /* AS */
1357
    if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
1358
        env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1359
        env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1360
    }
1361

    
1362
    env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1363
    env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1364

    
1365
    switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1366
    case MAS4_TIDSELD_PID0:
1367
        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
1368
        break;
1369
    case MAS4_TIDSELD_PID1:
1370
        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
1371
        break;
1372
    case MAS4_TIDSELD_PID2:
1373
        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
1374
        break;
1375
    }
1376

    
1377
    env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1378

    
1379
    /* next victim logic */
1380
    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1381
    env->last_way++;
1382
    env->last_way &= booke206_tlb_ways(env, 0) - 1;
1383
    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1384
}
1385

    
1386
/* Perform address translation */
1387
static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
1388
                                    int rw, int mmu_idx)
1389
{
1390
    mmu_ctx_t ctx;
1391
    int access_type;
1392
    int ret = 0;
1393

    
1394
    switch (env->mmu_model) {
1395
#if defined(TARGET_PPC64)
1396
    case POWERPC_MMU_64B:
1397
    case POWERPC_MMU_2_06:
1398
    case POWERPC_MMU_2_06d:
1399
        return ppc_hash64_handle_mmu_fault(env, address, rw, mmu_idx);
1400
#endif
1401

    
1402
    case POWERPC_MMU_32B:
1403
    case POWERPC_MMU_601:
1404
        return ppc_hash32_handle_mmu_fault(env, address, rw, mmu_idx);
1405

    
1406
    default:
1407
        ; /* Otherwise fall through to the general code below */
1408
    }
1409

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

    
1629
    return ret;
1630
}
1631

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

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

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

    
1658
void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1659
{
1660
    target_ulong mask;
1661

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

    
1684
void helper_store_ibatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1685
{
1686
    dump_store_bat(env, 'I', 1, nr, value);
1687
    env->IBAT[1][nr] = value;
1688
}
1689

    
1690
void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1691
{
1692
    target_ulong mask;
1693

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

    
1716
void helper_store_dbatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1717
{
1718
    dump_store_bat(env, 'D', 1, nr, value);
1719
    env->DBAT[1][nr] = value;
1720
}
1721

    
1722
void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
1723
{
1724
    target_ulong mask;
1725
#if defined(FLUSH_ALL_TLBS)
1726
    int do_inval;
1727
#endif
1728

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

    
1764
void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
1765
{
1766
#if !defined(FLUSH_ALL_TLBS)
1767
    target_ulong mask;
1768
#else
1769
    int do_inval;
1770
#endif
1771

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

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

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

    
1922
/*****************************************************************************/
1923
/* Special registers manipulation */
1924
void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
1925
{
1926
    LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
1927
    if (env->spr[SPR_SDR1] != value) {
1928
        env->spr[SPR_SDR1] = value;
1929
#if defined(TARGET_PPC64)
1930
        if (env->mmu_model & POWERPC_MMU_64) {
1931
            target_ulong htabsize = value & SDR_64_HTABSIZE;
1932

    
1933
            if (htabsize > 28) {
1934
                fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
1935
                        " stored in SDR1\n", htabsize);
1936
                htabsize = 28;
1937
            }
1938
            env->htab_mask = (1ULL << (htabsize + 18)) - 1;
1939
            env->htab_base = value & SDR_64_HTABORG;
1940
        } else
1941
#endif /* defined(TARGET_PPC64) */
1942
        {
1943
            /* FIXME: Should check for valid HTABMASK values */
1944
            env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
1945
            env->htab_base = value & SDR_32_HTABORG;
1946
        }
1947
        tlb_flush(env, 1);
1948
    }
1949
}
1950

    
1951
/* Segment registers load and store */
1952
target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num)
1953
{
1954
#if defined(TARGET_PPC64)
1955
    if (env->mmu_model & POWERPC_MMU_64) {
1956
        /* XXX */
1957
        return 0;
1958
    }
1959
#endif
1960
    return env->sr[sr_num];
1961
}
1962

    
1963
void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
1964
{
1965
    LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
1966
            (int)srnum, value, env->sr[srnum]);
1967
#if defined(TARGET_PPC64)
1968
    if (env->mmu_model & POWERPC_MMU_64) {
1969
        uint64_t rb = 0, rs = 0;
1970

    
1971
        /* ESID = srnum */
1972
        rb |= ((uint32_t)srnum & 0xf) << 28;
1973
        /* Set the valid bit */
1974
        rb |= 1 << 27;
1975
        /* Index = ESID */
1976
        rb |= (uint32_t)srnum;
1977

    
1978
        /* VSID = VSID */
1979
        rs |= (value & 0xfffffff) << 12;
1980
        /* flags = flags */
1981
        rs |= ((value >> 27) & 0xf) << 8;
1982

    
1983
        ppc_store_slb(env, rb, rs);
1984
    } else
1985
#endif
1986
    if (env->sr[srnum] != value) {
1987
        env->sr[srnum] = value;
1988
/* Invalidating 256MB of virtual memory in 4kB pages is way longer than
1989
   flusing the whole TLB. */
1990
#if !defined(FLUSH_ALL_TLBS) && 0
1991
        {
1992
            target_ulong page, end;
1993
            /* Invalidate 256 MB of virtual memory */
1994
            page = (16 << 20) * srnum;
1995
            end = page + (16 << 20);
1996
            for (; page != end; page += TARGET_PAGE_SIZE) {
1997
                tlb_flush_page(env, page);
1998
            }
1999
        }
2000
#else
2001
        tlb_flush(env, 1);
2002
#endif
2003
    }
2004
}
2005

    
2006
/* TLB management */
2007
void helper_tlbia(CPUPPCState *env)
2008
{
2009
    ppc_tlb_invalidate_all(env);
2010
}
2011

    
2012
void helper_tlbie(CPUPPCState *env, target_ulong addr)
2013
{
2014
    ppc_tlb_invalidate_one(env, addr);
2015
}
2016

    
2017
/* Software driven TLBs management */
2018
/* PowerPC 602/603 software TLB load instructions helpers */
2019
static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2020
{
2021
    target_ulong RPN, CMP, EPN;
2022
    int way;
2023

    
2024
    RPN = env->spr[SPR_RPA];
2025
    if (is_code) {
2026
        CMP = env->spr[SPR_ICMP];
2027
        EPN = env->spr[SPR_IMISS];
2028
    } else {
2029
        CMP = env->spr[SPR_DCMP];
2030
        EPN = env->spr[SPR_DMISS];
2031
    }
2032
    way = (env->spr[SPR_SRR1] >> 17) & 1;
2033
    (void)EPN; /* avoid a compiler warning */
2034
    LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2035
              " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2036
              RPN, way);
2037
    /* Store this TLB */
2038
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2039
                     way, is_code, CMP, RPN);
2040
}
2041

    
2042
void helper_6xx_tlbd(CPUPPCState *env, target_ulong EPN)
2043
{
2044
    do_6xx_tlb(env, EPN, 0);
2045
}
2046

    
2047
void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN)
2048
{
2049
    do_6xx_tlb(env, EPN, 1);
2050
}
2051

    
2052
/* PowerPC 74xx software TLB load instructions helpers */
2053
static void do_74xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2054
{
2055
    target_ulong RPN, CMP, EPN;
2056
    int way;
2057

    
2058
    RPN = env->spr[SPR_PTELO];
2059
    CMP = env->spr[SPR_PTEHI];
2060
    EPN = env->spr[SPR_TLBMISS] & ~0x3;
2061
    way = env->spr[SPR_TLBMISS] & 0x3;
2062
    (void)EPN; /* avoid a compiler warning */
2063
    LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2064
              " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2065
              RPN, way);
2066
    /* Store this TLB */
2067
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2068
                     way, is_code, CMP, RPN);
2069
}
2070

    
2071
void helper_74xx_tlbd(CPUPPCState *env, target_ulong EPN)
2072
{
2073
    do_74xx_tlb(env, EPN, 0);
2074
}
2075

    
2076
void helper_74xx_tlbi(CPUPPCState *env, target_ulong EPN)
2077
{
2078
    do_74xx_tlb(env, EPN, 1);
2079
}
2080

    
2081
/*****************************************************************************/
2082
/* PowerPC 601 specific instructions (POWER bridge) */
2083

    
2084
target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
2085
{
2086
    mmu_ctx_t ctx;
2087
    int nb_BATs;
2088
    target_ulong ret = 0;
2089

    
2090
    /* We don't have to generate many instances of this instruction,
2091
     * as rac is supervisor only.
2092
     */
2093
    /* XXX: FIX THIS: Pretend we have no BAT */
2094
    nb_BATs = env->nb_BATs;
2095
    env->nb_BATs = 0;
2096
    if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) {
2097
        ret = ctx.raddr;
2098
    }
2099
    env->nb_BATs = nb_BATs;
2100
    return ret;
2101
}
2102

    
2103
static inline target_ulong booke_tlb_to_page_size(int size)
2104
{
2105
    return 1024 << (2 * size);
2106
}
2107

    
2108
static inline int booke_page_size_to_tlb(target_ulong page_size)
2109
{
2110
    int size;
2111

    
2112
    switch (page_size) {
2113
    case 0x00000400UL:
2114
        size = 0x0;
2115
        break;
2116
    case 0x00001000UL:
2117
        size = 0x1;
2118
        break;
2119
    case 0x00004000UL:
2120
        size = 0x2;
2121
        break;
2122
    case 0x00010000UL:
2123
        size = 0x3;
2124
        break;
2125
    case 0x00040000UL:
2126
        size = 0x4;
2127
        break;
2128
    case 0x00100000UL:
2129
        size = 0x5;
2130
        break;
2131
    case 0x00400000UL:
2132
        size = 0x6;
2133
        break;
2134
    case 0x01000000UL:
2135
        size = 0x7;
2136
        break;
2137
    case 0x04000000UL:
2138
        size = 0x8;
2139
        break;
2140
    case 0x10000000UL:
2141
        size = 0x9;
2142
        break;
2143
    case 0x40000000UL:
2144
        size = 0xA;
2145
        break;
2146
#if defined(TARGET_PPC64)
2147
    case 0x000100000000ULL:
2148
        size = 0xB;
2149
        break;
2150
    case 0x000400000000ULL:
2151
        size = 0xC;
2152
        break;
2153
    case 0x001000000000ULL:
2154
        size = 0xD;
2155
        break;
2156
    case 0x004000000000ULL:
2157
        size = 0xE;
2158
        break;
2159
    case 0x010000000000ULL:
2160
        size = 0xF;
2161
        break;
2162
#endif
2163
    default:
2164
        size = -1;
2165
        break;
2166
    }
2167

    
2168
    return size;
2169
}
2170

    
2171
/* Helpers for 4xx TLB management */
2172
#define PPC4XX_TLB_ENTRY_MASK       0x0000003f  /* Mask for 64 TLB entries */
2173

    
2174
#define PPC4XX_TLBHI_V              0x00000040
2175
#define PPC4XX_TLBHI_E              0x00000020
2176
#define PPC4XX_TLBHI_SIZE_MIN       0
2177
#define PPC4XX_TLBHI_SIZE_MAX       7
2178
#define PPC4XX_TLBHI_SIZE_DEFAULT   1
2179
#define PPC4XX_TLBHI_SIZE_SHIFT     7
2180
#define PPC4XX_TLBHI_SIZE_MASK      0x00000007
2181

    
2182
#define PPC4XX_TLBLO_EX             0x00000200
2183
#define PPC4XX_TLBLO_WR             0x00000100
2184
#define PPC4XX_TLBLO_ATTR_MASK      0x000000FF
2185
#define PPC4XX_TLBLO_RPN_MASK       0xFFFFFC00
2186

    
2187
target_ulong helper_4xx_tlbre_hi(CPUPPCState *env, target_ulong entry)
2188
{
2189
    ppcemb_tlb_t *tlb;
2190
    target_ulong ret;
2191
    int size;
2192

    
2193
    entry &= PPC4XX_TLB_ENTRY_MASK;
2194
    tlb = &env->tlb.tlbe[entry];
2195
    ret = tlb->EPN;
2196
    if (tlb->prot & PAGE_VALID) {
2197
        ret |= PPC4XX_TLBHI_V;
2198
    }
2199
    size = booke_page_size_to_tlb(tlb->size);
2200
    if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) {
2201
        size = PPC4XX_TLBHI_SIZE_DEFAULT;
2202
    }
2203
    ret |= size << PPC4XX_TLBHI_SIZE_SHIFT;
2204
    env->spr[SPR_40x_PID] = tlb->PID;
2205
    return ret;
2206
}
2207

    
2208
target_ulong helper_4xx_tlbre_lo(CPUPPCState *env, target_ulong entry)
2209
{
2210
    ppcemb_tlb_t *tlb;
2211
    target_ulong ret;
2212

    
2213
    entry &= PPC4XX_TLB_ENTRY_MASK;
2214
    tlb = &env->tlb.tlbe[entry];
2215
    ret = tlb->RPN;
2216
    if (tlb->prot & PAGE_EXEC) {
2217
        ret |= PPC4XX_TLBLO_EX;
2218
    }
2219
    if (tlb->prot & PAGE_WRITE) {
2220
        ret |= PPC4XX_TLBLO_WR;
2221
    }
2222
    return ret;
2223
}
2224

    
2225
void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry,
2226
                         target_ulong val)
2227
{
2228
    ppcemb_tlb_t *tlb;
2229
    target_ulong page, end;
2230

    
2231
    LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry,
2232
              val);
2233
    entry &= PPC4XX_TLB_ENTRY_MASK;
2234
    tlb = &env->tlb.tlbe[entry];
2235
    /* Invalidate previous TLB (if it's valid) */
2236
    if (tlb->prot & PAGE_VALID) {
2237
        end = tlb->EPN + tlb->size;
2238
        LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end "
2239
                  TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2240
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2241
            tlb_flush_page(env, page);
2242
        }
2243
    }
2244
    tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT)
2245
                                       & PPC4XX_TLBHI_SIZE_MASK);
2246
    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2247
     * If this ever occurs, one should use the ppcemb target instead
2248
     * of the ppc or ppc64 one
2249
     */
2250
    if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) {
2251
        cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
2252
                  "are not supported (%d)\n",
2253
                  tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
2254
    }
2255
    tlb->EPN = val & ~(tlb->size - 1);
2256
    if (val & PPC4XX_TLBHI_V) {
2257
        tlb->prot |= PAGE_VALID;
2258
        if (val & PPC4XX_TLBHI_E) {
2259
            /* XXX: TO BE FIXED */
2260
            cpu_abort(env,
2261
                      "Little-endian TLB entries are not supported by now\n");
2262
        }
2263
    } else {
2264
        tlb->prot &= ~PAGE_VALID;
2265
    }
2266
    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2267
    LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2268
              " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2269
              (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2270
              tlb->prot & PAGE_READ ? 'r' : '-',
2271
              tlb->prot & PAGE_WRITE ? 'w' : '-',
2272
              tlb->prot & PAGE_EXEC ? 'x' : '-',
2273
              tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2274
    /* Invalidate new TLB (if valid) */
2275
    if (tlb->prot & PAGE_VALID) {
2276
        end = tlb->EPN + tlb->size;
2277
        LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end "
2278
                  TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2279
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2280
            tlb_flush_page(env, page);
2281
        }
2282
    }
2283
}
2284

    
2285
void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry,
2286
                         target_ulong val)
2287
{
2288
    ppcemb_tlb_t *tlb;
2289

    
2290
    LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry,
2291
              val);
2292
    entry &= PPC4XX_TLB_ENTRY_MASK;
2293
    tlb = &env->tlb.tlbe[entry];
2294
    tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
2295
    tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
2296
    tlb->prot = PAGE_READ;
2297
    if (val & PPC4XX_TLBLO_EX) {
2298
        tlb->prot |= PAGE_EXEC;
2299
    }
2300
    if (val & PPC4XX_TLBLO_WR) {
2301
        tlb->prot |= PAGE_WRITE;
2302
    }
2303
    LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2304
              " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2305
              (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2306
              tlb->prot & PAGE_READ ? 'r' : '-',
2307
              tlb->prot & PAGE_WRITE ? 'w' : '-',
2308
              tlb->prot & PAGE_EXEC ? 'x' : '-',
2309
              tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2310
}
2311

    
2312
target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address)
2313
{
2314
    return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
2315
}
2316

    
2317
/* PowerPC 440 TLB management */
2318
void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry,
2319
                      target_ulong value)
2320
{
2321
    ppcemb_tlb_t *tlb;
2322
    target_ulong EPN, RPN, size;
2323
    int do_flush_tlbs;
2324

    
2325
    LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx "\n",
2326
              __func__, word, (int)entry, value);
2327
    do_flush_tlbs = 0;
2328
    entry &= 0x3F;
2329
    tlb = &env->tlb.tlbe[entry];
2330
    switch (word) {
2331
    default:
2332
        /* Just here to please gcc */
2333
    case 0:
2334
        EPN = value & 0xFFFFFC00;
2335
        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) {
2336
            do_flush_tlbs = 1;
2337
        }
2338
        tlb->EPN = EPN;
2339
        size = booke_tlb_to_page_size((value >> 4) & 0xF);
2340
        if ((tlb->prot & PAGE_VALID) && tlb->size < size) {
2341
            do_flush_tlbs = 1;
2342
        }
2343
        tlb->size = size;
2344
        tlb->attr &= ~0x1;
2345
        tlb->attr |= (value >> 8) & 1;
2346
        if (value & 0x200) {
2347
            tlb->prot |= PAGE_VALID;
2348
        } else {
2349
            if (tlb->prot & PAGE_VALID) {
2350
                tlb->prot &= ~PAGE_VALID;
2351
                do_flush_tlbs = 1;
2352
            }
2353
        }
2354
        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
2355
        if (do_flush_tlbs) {
2356
            tlb_flush(env, 1);
2357
        }
2358
        break;
2359
    case 1:
2360
        RPN = value & 0xFFFFFC0F;
2361
        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) {
2362
            tlb_flush(env, 1);
2363
        }
2364
        tlb->RPN = RPN;
2365
        break;
2366
    case 2:
2367
        tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
2368
        tlb->prot = tlb->prot & PAGE_VALID;
2369
        if (value & 0x1) {
2370
            tlb->prot |= PAGE_READ << 4;
2371
        }
2372
        if (value & 0x2) {
2373
            tlb->prot |= PAGE_WRITE << 4;
2374
        }
2375
        if (value & 0x4) {
2376
            tlb->prot |= PAGE_EXEC << 4;
2377
        }
2378
        if (value & 0x8) {
2379
            tlb->prot |= PAGE_READ;
2380
        }
2381
        if (value & 0x10) {
2382
            tlb->prot |= PAGE_WRITE;
2383
        }
2384
        if (value & 0x20) {
2385
            tlb->prot |= PAGE_EXEC;
2386
        }
2387
        break;
2388
    }
2389
}
2390

    
2391
target_ulong helper_440_tlbre(CPUPPCState *env, uint32_t word,
2392
                              target_ulong entry)
2393
{
2394
    ppcemb_tlb_t *tlb;
2395
    target_ulong ret;
2396
    int size;
2397

    
2398
    entry &= 0x3F;
2399
    tlb = &env->tlb.tlbe[entry];
2400
    switch (word) {
2401
    default:
2402
        /* Just here to please gcc */
2403
    case 0:
2404
        ret = tlb->EPN;
2405
        size = booke_page_size_to_tlb(tlb->size);
2406
        if (size < 0 || size > 0xF) {
2407
            size = 1;
2408
        }
2409
        ret |= size << 4;
2410
        if (tlb->attr & 0x1) {
2411
            ret |= 0x100;
2412
        }
2413
        if (tlb->prot & PAGE_VALID) {
2414
            ret |= 0x200;
2415
        }
2416
        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2417
        env->spr[SPR_440_MMUCR] |= tlb->PID;
2418
        break;
2419
    case 1:
2420
        ret = tlb->RPN;
2421
        break;
2422
    case 2:
2423
        ret = tlb->attr & ~0x1;
2424
        if (tlb->prot & (PAGE_READ << 4)) {
2425
            ret |= 0x1;
2426
        }
2427
        if (tlb->prot & (PAGE_WRITE << 4)) {
2428
            ret |= 0x2;
2429
        }
2430
        if (tlb->prot & (PAGE_EXEC << 4)) {
2431
            ret |= 0x4;
2432
        }
2433
        if (tlb->prot & PAGE_READ) {
2434
            ret |= 0x8;
2435
        }
2436
        if (tlb->prot & PAGE_WRITE) {
2437
            ret |= 0x10;
2438
        }
2439
        if (tlb->prot & PAGE_EXEC) {
2440
            ret |= 0x20;
2441
        }
2442
        break;
2443
    }
2444
    return ret;
2445
}
2446

    
2447
target_ulong helper_440_tlbsx(CPUPPCState *env, target_ulong address)
2448
{
2449
    return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
2450
}
2451

    
2452
/* PowerPC BookE 2.06 TLB management */
2453

    
2454
static ppcmas_tlb_t *booke206_cur_tlb(CPUPPCState *env)
2455
{
2456
    uint32_t tlbncfg = 0;
2457
    int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
2458
    int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
2459
    int tlb;
2460

    
2461
    tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2462
    tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb];
2463

    
2464
    if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) {
2465
        cpu_abort(env, "we don't support HES yet\n");
2466
    }
2467

    
2468
    return booke206_get_tlbm(env, tlb, ea, esel);
2469
}
2470

    
2471
void helper_booke_setpid(CPUPPCState *env, uint32_t pidn, target_ulong pid)
2472
{
2473
    env->spr[pidn] = pid;
2474
    /* changing PIDs mean we're in a different address space now */
2475
    tlb_flush(env, 1);
2476
}
2477

    
2478
void helper_booke206_tlbwe(CPUPPCState *env)
2479
{
2480
    uint32_t tlbncfg, tlbn;
2481
    ppcmas_tlb_t *tlb;
2482
    uint32_t size_tlb, size_ps;
2483
    target_ulong mask;
2484

    
2485

    
2486
    switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
2487
    case MAS0_WQ_ALWAYS:
2488
        /* good to go, write that entry */
2489
        break;
2490
    case MAS0_WQ_COND:
2491
        /* XXX check if reserved */
2492
        if (0) {
2493
            return;
2494
        }
2495
        break;
2496
    case MAS0_WQ_CLR_RSRV:
2497
        /* XXX clear entry */
2498
        return;
2499
    default:
2500
        /* no idea what to do */
2501
        return;
2502
    }
2503

    
2504
    if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) &&
2505
        !msr_gs) {
2506
        /* XXX we don't support direct LRAT setting yet */
2507
        fprintf(stderr, "cpu: don't support LRAT setting yet\n");
2508
        return;
2509
    }
2510

    
2511
    tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2512
    tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
2513

    
2514
    tlb = booke206_cur_tlb(env);
2515

    
2516
    if (!tlb) {
2517
        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
2518
                                   POWERPC_EXCP_INVAL |
2519
                                   POWERPC_EXCP_INVAL_INVAL);
2520
    }
2521

    
2522
    /* check that we support the targeted size */
2523
    size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
2524
    size_ps = booke206_tlbnps(env, tlbn);
2525
    if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) &&
2526
        !(size_ps & (1 << size_tlb))) {
2527
        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
2528
                                   POWERPC_EXCP_INVAL |
2529
                                   POWERPC_EXCP_INVAL_INVAL);
2530
    }
2531

    
2532
    if (msr_gs) {
2533
        cpu_abort(env, "missing HV implementation\n");
2534
    }
2535
    tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
2536
        env->spr[SPR_BOOKE_MAS3];
2537
    tlb->mas1 = env->spr[SPR_BOOKE_MAS1];
2538

    
2539
    /* MAV 1.0 only */
2540
    if (!(tlbncfg & TLBnCFG_AVAIL)) {
2541
        /* force !AVAIL TLB entries to correct page size */
2542
        tlb->mas1 &= ~MAS1_TSIZE_MASK;
2543
        /* XXX can be configured in MMUCSR0 */
2544
        tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12;
2545
    }
2546

    
2547
    /* Make a mask from TLB size to discard invalid bits in EPN field */
2548
    mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2549
    /* Add a mask for page attributes */
2550
    mask |= MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E;
2551

    
2552
    if (!msr_cm) {
2553
        /* Executing a tlbwe instruction in 32-bit mode will set
2554
         * bits 0:31 of the TLB EPN field to zero.
2555
         */
2556
        mask &= 0xffffffff;
2557
    }
2558

    
2559
    tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & mask;
2560

    
2561
    if (!(tlbncfg & TLBnCFG_IPROT)) {
2562
        /* no IPROT supported by TLB */
2563
        tlb->mas1 &= ~MAS1_IPROT;
2564
    }
2565

    
2566
    if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) {
2567
        tlb_flush_page(env, tlb->mas2 & MAS2_EPN_MASK);
2568
    } else {
2569
        tlb_flush(env, 1);
2570
    }
2571
}
2572

    
2573
static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb)
2574
{
2575
    int tlbn = booke206_tlbm_to_tlbn(env, tlb);
2576
    int way = booke206_tlbm_to_way(env, tlb);
2577

    
2578
    env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT;
2579
    env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT;
2580
    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2581

    
2582
    env->spr[SPR_BOOKE_MAS1] = tlb->mas1;
2583
    env->spr[SPR_BOOKE_MAS2] = tlb->mas2;
2584
    env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3;
2585
    env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32;
2586
}
2587

    
2588
void helper_booke206_tlbre(CPUPPCState *env)
2589
{
2590
    ppcmas_tlb_t *tlb = NULL;
2591

    
2592
    tlb = booke206_cur_tlb(env);
2593
    if (!tlb) {
2594
        env->spr[SPR_BOOKE_MAS1] = 0;
2595
    } else {
2596
        booke206_tlb_to_mas(env, tlb);
2597
    }
2598
}
2599

    
2600
void helper_booke206_tlbsx(CPUPPCState *env, target_ulong address)
2601
{
2602
    ppcmas_tlb_t *tlb = NULL;
2603
    int i, j;
2604
    hwaddr raddr;
2605
    uint32_t spid, sas;
2606

    
2607
    spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT;
2608
    sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS;
2609

    
2610
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2611
        int ways = booke206_tlb_ways(env, i);
2612

    
2613
        for (j = 0; j < ways; j++) {
2614
            tlb = booke206_get_tlbm(env, i, address, j);
2615

    
2616
            if (!tlb) {
2617
                continue;
2618
            }
2619

    
2620
            if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
2621
                continue;
2622
            }
2623

    
2624
            if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
2625
                continue;
2626
            }
2627

    
2628
            booke206_tlb_to_mas(env, tlb);
2629
            return;
2630
        }
2631
    }
2632

    
2633
    /* no entry found, fill with defaults */
2634
    env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
2635
    env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
2636
    env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
2637
    env->spr[SPR_BOOKE_MAS3] = 0;
2638
    env->spr[SPR_BOOKE_MAS7] = 0;
2639

    
2640
    if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) {
2641
        env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
2642
    }
2643

    
2644
    env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16)
2645
        << MAS1_TID_SHIFT;
2646

    
2647
    /* next victim logic */
2648
    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
2649
    env->last_way++;
2650
    env->last_way &= booke206_tlb_ways(env, 0) - 1;
2651
    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2652
}
2653

    
2654
static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn,
2655
                                              uint32_t ea)
2656
{
2657
    int i;
2658
    int ways = booke206_tlb_ways(env, tlbn);
2659
    target_ulong mask;
2660

    
2661
    for (i = 0; i < ways; i++) {
2662
        ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
2663
        if (!tlb) {
2664
            continue;
2665
        }
2666
        mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2667
        if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
2668
            !(tlb->mas1 & MAS1_IPROT)) {
2669
            tlb->mas1 &= ~MAS1_VALID;
2670
        }
2671
    }
2672
}
2673

    
2674
void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address)
2675
{
2676
    if (address & 0x4) {
2677
        /* flush all entries */
2678
        if (address & 0x8) {
2679
            /* flush all of TLB1 */
2680
            booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1);
2681
        } else {
2682
            /* flush all of TLB0 */
2683
            booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0);
2684
        }
2685
        return;
2686
    }
2687

    
2688
    if (address & 0x8) {
2689
        /* flush TLB1 entries */
2690
        booke206_invalidate_ea_tlb(env, 1, address);
2691
        tlb_flush(env, 1);
2692
    } else {
2693
        /* flush TLB0 entries */
2694
        booke206_invalidate_ea_tlb(env, 0, address);
2695
        tlb_flush_page(env, address & MAS2_EPN_MASK);
2696
    }
2697
}
2698

    
2699
void helper_booke206_tlbilx0(CPUPPCState *env, target_ulong address)
2700
{
2701
    /* XXX missing LPID handling */
2702
    booke206_flush_tlb(env, -1, 1);
2703
}
2704

    
2705
void helper_booke206_tlbilx1(CPUPPCState *env, target_ulong address)
2706
{
2707
    int i, j;
2708
    int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2709
    ppcmas_tlb_t *tlb = env->tlb.tlbm;
2710
    int tlb_size;
2711

    
2712
    /* XXX missing LPID handling */
2713
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2714
        tlb_size = booke206_tlb_size(env, i);
2715
        for (j = 0; j < tlb_size; j++) {
2716
            if (!(tlb[j].mas1 & MAS1_IPROT) &&
2717
                ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) {
2718
                tlb[j].mas1 &= ~MAS1_VALID;
2719
            }
2720
        }
2721
        tlb += booke206_tlb_size(env, i);
2722
    }
2723
    tlb_flush(env, 1);
2724
}
2725

    
2726
void helper_booke206_tlbilx3(CPUPPCState *env, target_ulong address)
2727
{
2728
    int i, j;
2729
    ppcmas_tlb_t *tlb;
2730
    int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2731
    int pid = tid >> MAS6_SPID_SHIFT;
2732
    int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS;
2733
    int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0;
2734
    /* XXX check for unsupported isize and raise an invalid opcode then */
2735
    int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK;
2736
    /* XXX implement MAV2 handling */
2737
    bool mav2 = false;
2738

    
2739
    /* XXX missing LPID handling */
2740
    /* flush by pid and ea */
2741
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2742
        int ways = booke206_tlb_ways(env, i);
2743

    
2744
        for (j = 0; j < ways; j++) {
2745
            tlb = booke206_get_tlbm(env, i, address, j);
2746
            if (!tlb) {
2747
                continue;
2748
            }
2749
            if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
2750
                (tlb->mas1 & MAS1_IPROT) ||
2751
                ((tlb->mas1 & MAS1_IND) != ind) ||
2752
                ((tlb->mas8 & MAS8_TGS) != sgs)) {
2753
                continue;
2754
            }
2755
            if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) {
2756
                /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2757
                continue;
2758
            }
2759
            /* XXX e500mc doesn't match SAS, but other cores might */
2760
            tlb->mas1 &= ~MAS1_VALID;
2761
        }
2762
    }
2763
    tlb_flush(env, 1);
2764
}
2765

    
2766
void helper_booke206_tlbflush(CPUPPCState *env, uint32_t type)
2767
{
2768
    int flags = 0;
2769

    
2770
    if (type & 2) {
2771
        flags |= BOOKE206_FLUSH_TLB1;
2772
    }
2773

    
2774
    if (type & 4) {
2775
        flags |= BOOKE206_FLUSH_TLB0;
2776
    }
2777

    
2778
    booke206_flush_tlb(env, flags, 1);
2779
}
2780

    
2781

    
2782
/*****************************************************************************/
2783

    
2784
#define MMUSUFFIX _mmu
2785

    
2786
#define SHIFT 0
2787
#include "exec/softmmu_template.h"
2788

    
2789
#define SHIFT 1
2790
#include "exec/softmmu_template.h"
2791

    
2792
#define SHIFT 2
2793
#include "exec/softmmu_template.h"
2794

    
2795
#define SHIFT 3
2796
#include "exec/softmmu_template.h"
2797

    
2798
/* try to fill the TLB and return an exception if error. If retaddr is
2799
   NULL, it means that the function was called in C code (i.e. not
2800
   from generated code or from helper.c) */
2801
/* XXX: fix it to restore all registers */
2802
void tlb_fill(CPUPPCState *env, target_ulong addr, int is_write, int mmu_idx,
2803
              uintptr_t retaddr)
2804
{
2805
    int ret;
2806

    
2807
    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx);
2808
    if (unlikely(ret != 0)) {
2809
        if (likely(retaddr)) {
2810
            /* now we have a real cpu fault */
2811
            cpu_restore_state(env, retaddr);
2812
        }
2813
        helper_raise_exception_err(env, env->exception_index, env->error_code);
2814
    }
2815
}