Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ cdaee006

History | View | Annotate | Download (91.2 kB)

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

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

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

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

    
48

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

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

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

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

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

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

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

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

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

    
101
    return 1;
102
}
103

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

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

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

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

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

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

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

    
172
    return access;
173
}
174

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

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

    
196
    return ret;
197
}
198

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

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

    
257
    return ret;
258
}
259

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

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

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

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

    
296
    return store;
297
}
298

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

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

    
313
    return nr;
314
}
315

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

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

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

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

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

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

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

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

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

    
441
    return ret;
442
}
443

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

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

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

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

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

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

    
570
static inline target_phys_addr_t get_pteg_offset(CPUState *env,
571
                                                 target_phys_addr_t hash,
572
                                                 int pte_size)
573
{
574
    return (hash * pte_size * 8) & env->htab_mask;
575
}
576

    
577
/* PTE table lookup */
578
static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
579
                            int rw, int type, int target_page_bits)
580
{
581
    target_phys_addr_t pteg_off;
582
    target_ulong pte0, pte1;
583
    int i, good = -1;
584
    int ret, r;
585

    
586
    ret = -1; /* No entry found */
587
    pteg_off = get_pteg_offset(env, ctx->hash[h],
588
                               is_64b ? HASH_PTE_SIZE_64 : HASH_PTE_SIZE_32);
589
    for (i = 0; i < 8; i++) {
590
#if defined(TARGET_PPC64)
591
        if (is_64b) {
592
            pte0 = ldq_phys(env->htab_base + pteg_off + (i * 16));
593
            pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
594

    
595
            /* We have a TLB that saves 4K pages, so let's
596
             * split a huge page to 4k chunks */
597
            if (target_page_bits != TARGET_PAGE_BITS)
598
                pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1))
599
                        & TARGET_PAGE_MASK;
600

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

    
661
    return ret;
662
}
663

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

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

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

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

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

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

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

    
702
    return NULL;
703
}
704

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

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

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

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

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

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

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

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

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

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

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

    
770
    return 0;
771
}
772

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
972
    return ret;
973
}
974

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

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

    
1005
    return 0;
1006
}
1007

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

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

    
1025
    return ret;
1026
}
1027

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

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

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

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

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

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

    
1124
    return ret;
1125
}
1126

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

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

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

    
1179
    return ret;
1180
}
1181

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

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

    
1245
    return ret;
1246
}
1247

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

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

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

    
1326
    return ctx.raddr & TARGET_PAGE_MASK;
1327
}
1328

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

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

    
1608
    return ret;
1609
}
1610

    
1611
/*****************************************************************************/
1612
/* BATs management */
1613
#if !defined(FLUSH_ALL_TLBS)
1614
static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1615
                                     target_ulong mask)
1616
{
1617
    target_ulong base, end, page;
1618

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

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

    
1636
void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1637
{
1638
    target_ulong mask;
1639

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

    
1662
void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1663
{
1664
    dump_store_bat(env, 'I', 1, nr, value);
1665
    env->IBAT[1][nr] = value;
1666
}
1667

    
1668
void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1669
{
1670
    target_ulong mask;
1671

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

    
1694
void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1695
{
1696
    dump_store_bat(env, 'D', 1, nr, value);
1697
    env->DBAT[1][nr] = value;
1698
}
1699

    
1700
void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1701
{
1702
    target_ulong mask;
1703
#if defined(FLUSH_ALL_TLBS)
1704
    int do_inval;
1705
#endif
1706

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

    
1741
void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1742
{
1743
    target_ulong mask;
1744
#if defined(FLUSH_ALL_TLBS)
1745
    int do_inval;
1746
#endif
1747

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

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

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

    
1896
/*****************************************************************************/
1897
/* Special registers manipulation */
1898
#if defined(TARGET_PPC64)
1899
void ppc_store_asr (CPUPPCState *env, target_ulong value)
1900
{
1901
    if (env->asr != value) {
1902
        env->asr = value;
1903
        tlb_flush(env, 1);
1904
    }
1905
}
1906
#endif
1907

    
1908
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
1909
{
1910
    LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
1911
    if (env->spr[SPR_SDR1] != value) {
1912
        env->spr[SPR_SDR1] = value;
1913
#if defined(TARGET_PPC64)
1914
        if (env->mmu_model & POWERPC_MMU_64) {
1915
            target_ulong htabsize = value & SDR_64_HTABSIZE;
1916

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

    
1935
#if defined(TARGET_PPC64)
1936
target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
1937
{
1938
    // XXX
1939
    return 0;
1940
}
1941
#endif
1942

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

    
1951
        /* ESID = srnum */
1952
        rb |= ((uint32_t)srnum & 0xf) << 28;
1953
        /* Set the valid bit */
1954
        rb |= 1 << 27;
1955
        /* Index = ESID */
1956
        rb |= (uint32_t)srnum;
1957

    
1958
        /* VSID = VSID */
1959
        rs |= (value & 0xfffffff) << 12;
1960
        /* flags = flags */
1961
        rs |= ((value >> 27) & 0xf) << 9;
1962

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

    
1986
/* GDBstub can read and write MSR... */
1987
void ppc_store_msr (CPUPPCState *env, target_ulong value)
1988
{
1989
    hreg_store_msr(env, value, 0);
1990
}
1991

    
1992
/*****************************************************************************/
1993
/* Exception processing */
1994
#if defined (CONFIG_USER_ONLY)
1995
void do_interrupt (CPUState *env)
1996
{
1997
    env->exception_index = POWERPC_EXCP_NONE;
1998
    env->error_code = 0;
1999
}
2000

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

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

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

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

    
2039
    /* new srr1 value excluding must-be-zero bits */
2040
    msr = env->msr & ~0x783f0000ULL;
2041

    
2042
    /* new interrupt handler msr */
2043
    new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2044

    
2045
    /* target registers */
2046
    srr0 = SPR_SRR0;
2047
    srr1 = SPR_SRR1;
2048
    asrr0 = -1;
2049
    asrr1 = -1;
2050

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

    
2091
        /* machine check exceptions don't have ME set */
2092
        new_msr &= ~((target_ulong)1 << MSR_ME);
2093

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

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

    
2530
    if (msr_ile) {
2531
        new_msr |= (target_ulong)1 << MSR_LE;
2532
    }
2533

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

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

    
2574
void do_interrupt (CPUState *env)
2575
{
2576
    powerpc_excp(env, env->excp_model, env->exception_index);
2577
}
2578

    
2579
void ppc_hw_interrupt (CPUPPCState *env)
2580
{
2581
    int hdice;
2582

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

    
2696
void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2697
{
2698
    qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
2699
             TARGET_FMT_lx "\n", RA, msr);
2700
}
2701

    
2702
void cpu_reset(CPUPPCState *env)
2703
{
2704
    target_ulong msr;
2705

    
2706
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
2707
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
2708
        log_cpu_state(env, 0);
2709
    }
2710

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

    
2750
CPUPPCState *cpu_ppc_init (const char *cpu_model)
2751
{
2752
    CPUPPCState *env;
2753
    const ppc_def_t *def;
2754

    
2755
    def = cpu_ppc_find_by_name(cpu_model);
2756
    if (!def)
2757
        return NULL;
2758

    
2759
    env = qemu_mallocz(sizeof(CPUPPCState));
2760
    cpu_exec_init(env);
2761
    ppc_translate_init();
2762
    env->cpu_model_str = cpu_model;
2763
    cpu_ppc_register_internal(env, def);
2764

    
2765
    qemu_init_vcpu(env);
2766

    
2767
    return env;
2768
}
2769

    
2770
void cpu_ppc_close (CPUPPCState *env)
2771
{
2772
    /* Should also remove all opcode tables... */
2773
    qemu_free(env);
2774
}