Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ 7267c094

History | View | Annotate | Download (101.3 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

    
25
#include "cpu.h"
26
#include "helper_regs.h"
27
#include "qemu-common.h"
28
#include "kvm.h"
29

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

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

    
46

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

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

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

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

    
71
/*****************************************************************************/
72
/* PowerPC Hypercall emulation */
73

    
74
void (*cpu_ppc_hypercall)(CPUState *);
75

    
76
/*****************************************************************************/
77
/* PowerPC MMU emulation */
78

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

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

    
99
    return 1;
100
}
101

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

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

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

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

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

    
133
static inline int pp_check(int key, int pp, int nx)
134
{
135
    int access;
136

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

    
170
    return access;
171
}
172

    
173
static inline int check_prot(int prot, int rw, int access_type)
174
{
175
    int ret;
176

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

    
194
    return ret;
195
}
196

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

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

    
255
    return ret;
256
}
257

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

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

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

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

    
294
    return store;
295
}
296

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

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

    
311
    return nr;
312
}
313

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

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

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

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

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

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

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

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

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

    
439
    return ret;
440
}
441

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

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

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

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

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

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

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

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

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

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

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

    
679
    return ret;
680
}
681

    
682
static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
683
                           int type, int target_page_bits)
684
{
685
#if defined(TARGET_PPC64)
686
    if (env->mmu_model & POWERPC_MMU_64)
687
        return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
688
#endif
689

    
690
    return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
691
}
692

    
693
#if defined(TARGET_PPC64)
694
static inline ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
695
{
696
    uint64_t esid_256M, esid_1T;
697
    int n;
698

    
699
    LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
700

    
701
    esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
702
    esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V;
703

    
704
    for (n = 0; n < env->slb_nr; n++) {
705
        ppc_slb_t *slb = &env->slb[n];
706

    
707
        LOG_SLB("%s: slot %d %016" PRIx64 " %016"
708
                    PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
709
        /* We check for 1T matches on all MMUs here - if the MMU
710
         * doesn't have 1T segment support, we will have prevented 1T
711
         * entries from being inserted in the slbmte code. */
712
        if (((slb->esid == esid_256M) &&
713
             ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_256M))
714
            || ((slb->esid == esid_1T) &&
715
                ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_1T))) {
716
            return slb;
717
        }
718
    }
719

    
720
    return NULL;
721
}
722

    
723
void ppc_slb_invalidate_all (CPUPPCState *env)
724
{
725
    int n, do_invalidate;
726

    
727
    do_invalidate = 0;
728
    /* XXX: Warning: slbia never invalidates the first segment */
729
    for (n = 1; n < env->slb_nr; n++) {
730
        ppc_slb_t *slb = &env->slb[n];
731

    
732
        if (slb->esid & SLB_ESID_V) {
733
            slb->esid &= ~SLB_ESID_V;
734
            /* XXX: given the fact that segment size is 256 MB or 1TB,
735
             *      and we still don't have a tlb_flush_mask(env, n, mask)
736
             *      in Qemu, we just invalidate all TLBs
737
             */
738
            do_invalidate = 1;
739
        }
740
    }
741
    if (do_invalidate)
742
        tlb_flush(env, 1);
743
}
744

    
745
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
746
{
747
    ppc_slb_t *slb;
748

    
749
    slb = slb_lookup(env, T0);
750
    if (!slb) {
751
        return;
752
    }
753

    
754
    if (slb->esid & SLB_ESID_V) {
755
        slb->esid &= ~SLB_ESID_V;
756

    
757
        /* XXX: given the fact that segment size is 256 MB or 1TB,
758
         *      and we still don't have a tlb_flush_mask(env, n, mask)
759
         *      in Qemu, we just invalidate all TLBs
760
         */
761
        tlb_flush(env, 1);
762
    }
763
}
764

    
765
int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
766
{
767
    int slot = rb & 0xfff;
768
    ppc_slb_t *slb = &env->slb[slot];
769

    
770
    if (rb & (0x1000 - env->slb_nr)) {
771
        return -1; /* Reserved bits set or slot too high */
772
    }
773
    if (rs & (SLB_VSID_B & ~SLB_VSID_B_1T)) {
774
        return -1; /* Bad segment size */
775
    }
776
    if ((rs & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG)) {
777
        return -1; /* 1T segment on MMU that doesn't support it */
778
    }
779

    
780
    /* Mask out the slot number as we store the entry */
781
    slb->esid = rb & (SLB_ESID_ESID | SLB_ESID_V);
782
    slb->vsid = rs;
783

    
784
    LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
785
            " %016" PRIx64 "\n", __func__, slot, rb, rs,
786
            slb->esid, slb->vsid);
787

    
788
    return 0;
789
}
790

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

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

    
800
    *rt = slb->esid;
801
    return 0;
802
}
803

    
804
int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
805
{
806
    int slot = rb & 0xfff;
807
    ppc_slb_t *slb = &env->slb[slot];
808

    
809
    if (slot >= env->slb_nr) {
810
        return -1;
811
    }
812

    
813
    *rt = slb->vsid;
814
    return 0;
815
}
816
#endif /* defined(TARGET_PPC64) */
817

    
818
/* Perform segment based translation */
819
static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
820
                              target_ulong eaddr, int rw, int type)
821
{
822
    target_phys_addr_t hash;
823
    target_ulong vsid;
824
    int ds, pr, target_page_bits;
825
    int ret, ret2;
826

    
827
    pr = msr_pr;
828
    ctx->eaddr = eaddr;
829
#if defined(TARGET_PPC64)
830
    if (env->mmu_model & POWERPC_MMU_64) {
831
        ppc_slb_t *slb;
832
        target_ulong pageaddr;
833
        int segment_bits;
834

    
835
        LOG_MMU("Check SLBs\n");
836
        slb = slb_lookup(env, eaddr);
837
        if (!slb) {
838
            return -5;
839
        }
840

    
841
        if (slb->vsid & SLB_VSID_B) {
842
            vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
843
            segment_bits = 40;
844
        } else {
845
            vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
846
            segment_bits = 28;
847
        }
848

    
849
        target_page_bits = (slb->vsid & SLB_VSID_L)
850
            ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
851
        ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
852
                      : (slb->vsid & SLB_VSID_KS));
853
        ds = 0;
854
        ctx->nx = !!(slb->vsid & SLB_VSID_N);
855

    
856
        pageaddr = eaddr & ((1ULL << segment_bits)
857
                            - (1ULL << target_page_bits));
858
        if (slb->vsid & SLB_VSID_B) {
859
            hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
860
        } else {
861
            hash = vsid ^ (pageaddr >> target_page_bits);
862
        }
863
        /* Only 5 bits of the page index are used in the AVPN */
864
        ctx->ptem = (slb->vsid & SLB_VSID_PTEM) |
865
            ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
866
    } else
867
#endif /* defined(TARGET_PPC64) */
868
    {
869
        target_ulong sr, pgidx;
870

    
871
        sr = env->sr[eaddr >> 28];
872
        ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
873
                    ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
874
        ds = sr & 0x80000000 ? 1 : 0;
875
        ctx->nx = sr & 0x10000000 ? 1 : 0;
876
        vsid = sr & 0x00FFFFFF;
877
        target_page_bits = TARGET_PAGE_BITS;
878
        LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
879
                TARGET_FMT_lx " lr=" TARGET_FMT_lx
880
                " ir=%d dr=%d pr=%d %d t=%d\n",
881
                eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
882
                (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
883
        pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
884
        hash = vsid ^ pgidx;
885
        ctx->ptem = (vsid << 7) | (pgidx >> 10);
886
    }
887
    LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
888
            ctx->key, ds, ctx->nx, vsid);
889
    ret = -1;
890
    if (!ds) {
891
        /* Check if instruction fetch is allowed, if needed */
892
        if (type != ACCESS_CODE || ctx->nx == 0) {
893
            /* Page address translation */
894
            LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
895
                    " hash " TARGET_FMT_plx "\n",
896
                    env->htab_base, env->htab_mask, hash);
897
            ctx->hash[0] = hash;
898
            ctx->hash[1] = ~hash;
899

    
900
            /* Initialize real address with an invalid value */
901
            ctx->raddr = (target_phys_addr_t)-1ULL;
902
            if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
903
                         env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
904
                /* Software TLB search */
905
                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
906
            } else {
907
                LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
908
                        " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
909
                        " hash=" TARGET_FMT_plx "\n",
910
                        env->htab_base, env->htab_mask, vsid, ctx->ptem,
911
                        ctx->hash[0]);
912
                /* Primary table lookup */
913
                ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
914
                if (ret < 0) {
915
                    /* Secondary table lookup */
916
                    if (eaddr != 0xEFFFFFFF)
917
                        LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
918
                                " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
919
                                " hash=" TARGET_FMT_plx "\n", env->htab_base,
920
                                env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
921
                    ret2 = find_pte(env, ctx, 1, rw, type,
922
                                    target_page_bits);
923
                    if (ret2 != -1)
924
                        ret = ret2;
925
                }
926
            }
927
#if defined (DUMP_PAGE_TABLES)
928
            if (qemu_log_enabled()) {
929
                target_phys_addr_t curaddr;
930
                uint32_t a0, a1, a2, a3;
931
                qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
932
                         "\n", sdr, mask + 0x80);
933
                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
934
                     curaddr += 16) {
935
                    a0 = ldl_phys(curaddr);
936
                    a1 = ldl_phys(curaddr + 4);
937
                    a2 = ldl_phys(curaddr + 8);
938
                    a3 = ldl_phys(curaddr + 12);
939
                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
940
                        qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
941
                                 curaddr, a0, a1, a2, a3);
942
                    }
943
                }
944
            }
945
#endif
946
        } else {
947
            LOG_MMU("No access allowed\n");
948
            ret = -3;
949
        }
950
    } else {
951
        target_ulong sr;
952
        LOG_MMU("direct store...\n");
953
        /* Direct-store segment : absolutely *BUGGY* for now */
954

    
955
        /* Direct-store implies a 32-bit MMU.
956
         * Check the Segment Register's bus unit ID (BUID).
957
         */
958
        sr = env->sr[eaddr >> 28];
959
        if ((sr & 0x1FF00000) >> 20 == 0x07f) {
960
            /* Memory-forced I/O controller interface access */
961
            /* If T=1 and BUID=x'07F', the 601 performs a memory access
962
             * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
963
             */
964
            ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
965
            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
966
            return 0;
967
        }
968

    
969
        switch (type) {
970
        case ACCESS_INT:
971
            /* Integer load/store : only access allowed */
972
            break;
973
        case ACCESS_CODE:
974
            /* No code fetch is allowed in direct-store areas */
975
            return -4;
976
        case ACCESS_FLOAT:
977
            /* Floating point load/store */
978
            return -4;
979
        case ACCESS_RES:
980
            /* lwarx, ldarx or srwcx. */
981
            return -4;
982
        case ACCESS_CACHE:
983
            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
984
            /* Should make the instruction do no-op.
985
             * As it already do no-op, it's quite easy :-)
986
             */
987
            ctx->raddr = eaddr;
988
            return 0;
989
        case ACCESS_EXT:
990
            /* eciwx or ecowx */
991
            return -4;
992
        default:
993
            qemu_log("ERROR: instruction should not need "
994
                        "address translation\n");
995
            return -4;
996
        }
997
        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
998
            ctx->raddr = eaddr;
999
            ret = 2;
1000
        } else {
1001
            ret = -2;
1002
        }
1003
    }
1004

    
1005
    return ret;
1006
}
1007

    
1008
/* Generic TLB check function for embedded PowerPC implementations */
1009
int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
1010
                     target_phys_addr_t *raddrp,
1011
                     target_ulong address, uint32_t pid, int ext,
1012
                     int i)
1013
{
1014
    target_ulong mask;
1015

    
1016
    /* Check valid flag */
1017
    if (!(tlb->prot & PAGE_VALID)) {
1018
        return -1;
1019
    }
1020
    mask = ~(tlb->size - 1);
1021
    LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
1022
              " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
1023
              mask, (uint32_t)tlb->PID, tlb->prot);
1024
    /* Check PID */
1025
    if (tlb->PID != 0 && tlb->PID != pid)
1026
        return -1;
1027
    /* Check effective address */
1028
    if ((address & mask) != tlb->EPN)
1029
        return -1;
1030
    *raddrp = (tlb->RPN & mask) | (address & ~mask);
1031
#if (TARGET_PHYS_ADDR_BITS >= 36)
1032
    if (ext) {
1033
        /* Extend the physical address to 36 bits */
1034
        *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1035
    }
1036
#endif
1037

    
1038
    return 0;
1039
}
1040

    
1041
/* Generic TLB search function for PowerPC embedded implementations */
1042
int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1043
{
1044
    ppcemb_tlb_t *tlb;
1045
    target_phys_addr_t raddr;
1046
    int i, ret;
1047

    
1048
    /* Default return value is no match */
1049
    ret = -1;
1050
    for (i = 0; i < env->nb_tlb; i++) {
1051
        tlb = &env->tlb.tlbe[i];
1052
        if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1053
            ret = i;
1054
            break;
1055
        }
1056
    }
1057

    
1058
    return ret;
1059
}
1060

    
1061
/* Helpers specific to PowerPC 40x implementations */
1062
static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
1063
{
1064
    ppcemb_tlb_t *tlb;
1065
    int i;
1066

    
1067
    for (i = 0; i < env->nb_tlb; i++) {
1068
        tlb = &env->tlb.tlbe[i];
1069
        tlb->prot &= ~PAGE_VALID;
1070
    }
1071
    tlb_flush(env, 1);
1072
}
1073

    
1074
static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
1075
                                              target_ulong eaddr, uint32_t pid)
1076
{
1077
#if !defined(FLUSH_ALL_TLBS)
1078
    ppcemb_tlb_t *tlb;
1079
    target_phys_addr_t raddr;
1080
    target_ulong page, end;
1081
    int i;
1082

    
1083
    for (i = 0; i < env->nb_tlb; i++) {
1084
        tlb = &env->tlb.tlbe[i];
1085
        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1086
            end = tlb->EPN + tlb->size;
1087
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1088
                tlb_flush_page(env, page);
1089
            tlb->prot &= ~PAGE_VALID;
1090
            break;
1091
        }
1092
    }
1093
#else
1094
    ppc4xx_tlb_invalidate_all(env);
1095
#endif
1096
}
1097

    
1098
static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1099
                                 target_ulong address, int rw, int access_type)
1100
{
1101
    ppcemb_tlb_t *tlb;
1102
    target_phys_addr_t raddr;
1103
    int i, ret, zsel, zpr, pr;
1104

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

    
1157
    return ret;
1158
}
1159

    
1160
void store_40x_sler (CPUPPCState *env, uint32_t val)
1161
{
1162
    /* XXX: TO BE FIXED */
1163
    if (val != 0x00000000) {
1164
        cpu_abort(env, "Little-endian regions are not supported by now\n");
1165
    }
1166
    env->spr[SPR_405_SLER] = val;
1167
}
1168

    
1169
static inline int mmubooke_check_tlb (CPUState *env, ppcemb_tlb_t *tlb,
1170
                                      target_phys_addr_t *raddr, int *prot,
1171
                                      target_ulong address, int rw,
1172
                                      int access_type, int i)
1173
{
1174
    int ret, _prot;
1175

    
1176
    if (ppcemb_tlb_check(env, tlb, raddr, address,
1177
                         env->spr[SPR_BOOKE_PID],
1178
                         !env->nb_pids, i) >= 0) {
1179
        goto found_tlb;
1180
    }
1181

    
1182
    if (env->spr[SPR_BOOKE_PID1] &&
1183
        ppcemb_tlb_check(env, tlb, raddr, address,
1184
                         env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
1185
        goto found_tlb;
1186
    }
1187

    
1188
    if (env->spr[SPR_BOOKE_PID2] &&
1189
        ppcemb_tlb_check(env, tlb, raddr, address,
1190
                         env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
1191
        goto found_tlb;
1192
    }
1193

    
1194
    LOG_SWTLB("%s: TLB entry not found\n", __func__);
1195
    return -1;
1196

    
1197
found_tlb:
1198

    
1199
    if (msr_pr != 0) {
1200
        _prot = tlb->prot & 0xF;
1201
    } else {
1202
        _prot = (tlb->prot >> 4) & 0xF;
1203
    }
1204

    
1205
    /* Check the address space */
1206
    if (access_type == ACCESS_CODE) {
1207
        if (msr_ir != (tlb->attr & 1)) {
1208
            LOG_SWTLB("%s: AS doesn't match\n", __func__);
1209
            return -1;
1210
        }
1211

    
1212
        *prot = _prot;
1213
        if (_prot & PAGE_EXEC) {
1214
            LOG_SWTLB("%s: good TLB!\n", __func__);
1215
            return 0;
1216
        }
1217

    
1218
        LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
1219
        ret = -3;
1220
    } else {
1221
        if (msr_dr != (tlb->attr & 1)) {
1222
            LOG_SWTLB("%s: AS doesn't match\n", __func__);
1223
            return -1;
1224
        }
1225

    
1226
        *prot = _prot;
1227
        if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
1228
            LOG_SWTLB("%s: found TLB!\n", __func__);
1229
            return 0;
1230
        }
1231

    
1232
        LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
1233
        ret = -2;
1234
    }
1235

    
1236
    return ret;
1237
}
1238

    
1239
static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1240
                                          target_ulong address, int rw,
1241
                                          int access_type)
1242
{
1243
    ppcemb_tlb_t *tlb;
1244
    target_phys_addr_t raddr;
1245
    int i, ret;
1246

    
1247
    ret = -1;
1248
    raddr = (target_phys_addr_t)-1ULL;
1249
    for (i = 0; i < env->nb_tlb; i++) {
1250
        tlb = &env->tlb.tlbe[i];
1251
        ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
1252
                                 access_type, i);
1253
        if (!ret) {
1254
            break;
1255
        }
1256
    }
1257

    
1258
    if (ret >= 0) {
1259
        ctx->raddr = raddr;
1260
        LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1261
                  " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1262
                  ret);
1263
    } else {
1264
        LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1265
                  " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1266
    }
1267

    
1268
    return ret;
1269
}
1270

    
1271
void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
1272
{
1273
    int tlb_size;
1274
    int i, j;
1275
    ppcmas_tlb_t *tlb = env->tlb.tlbm;
1276

    
1277
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1278
        if (flags & (1 << i)) {
1279
            tlb_size = booke206_tlb_size(env, i);
1280
            for (j = 0; j < tlb_size; j++) {
1281
                if (!check_iprot || !(tlb[j].mas1 & MAS1_IPROT)) {
1282
                    tlb[j].mas1 &= ~MAS1_VALID;
1283
                }
1284
            }
1285
        }
1286
        tlb += booke206_tlb_size(env, i);
1287
    }
1288

    
1289
    tlb_flush(env, 1);
1290
}
1291

    
1292
target_phys_addr_t booke206_tlb_to_page_size(CPUState *env, ppcmas_tlb_t *tlb)
1293
{
1294
    uint32_t tlbncfg;
1295
    int tlbn = booke206_tlbm_to_tlbn(env, tlb);
1296
    target_phys_addr_t tlbm_size;
1297

    
1298
    tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
1299

    
1300
    if (tlbncfg & TLBnCFG_AVAIL) {
1301
        tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1302
    } else {
1303
        tlbm_size = (tlbncfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
1304
    }
1305

    
1306
    return (1 << (tlbm_size << 1)) << 10;
1307
}
1308

    
1309
/* TLB check function for MAS based SoftTLBs */
1310
int ppcmas_tlb_check(CPUState *env, ppcmas_tlb_t *tlb,
1311
                     target_phys_addr_t *raddrp,
1312
                     target_ulong address, uint32_t pid)
1313
{
1314
    target_ulong mask;
1315
    uint32_t tlb_pid;
1316

    
1317
    /* Check valid flag */
1318
    if (!(tlb->mas1 & MAS1_VALID)) {
1319
        return -1;
1320
    }
1321

    
1322
    mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
1323
    LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%"
1324
              PRIx64 " mask=0x" TARGET_FMT_lx " MAS7_3=0x%" PRIx64 " MAS8=%x\n",
1325
              __func__, address, pid, tlb->mas1, tlb->mas2, mask, tlb->mas7_3,
1326
              tlb->mas8);
1327

    
1328
    /* Check PID */
1329
    tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
1330
    if (tlb_pid != 0 && tlb_pid != pid) {
1331
        return -1;
1332
    }
1333

    
1334
    /* Check effective address */
1335
    if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
1336
        return -1;
1337
    }
1338
    *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
1339

    
1340
    return 0;
1341
}
1342

    
1343
static int mmubooke206_check_tlb(CPUState *env, ppcmas_tlb_t *tlb,
1344
                                 target_phys_addr_t *raddr, int *prot,
1345
                                 target_ulong address, int rw,
1346
                                 int access_type)
1347
{
1348
    int ret;
1349
    int _prot = 0;
1350

    
1351
    if (ppcmas_tlb_check(env, tlb, raddr, address,
1352
                         env->spr[SPR_BOOKE_PID]) >= 0) {
1353
        goto found_tlb;
1354
    }
1355

    
1356
    if (env->spr[SPR_BOOKE_PID1] &&
1357
        ppcmas_tlb_check(env, tlb, raddr, address,
1358
                         env->spr[SPR_BOOKE_PID1]) >= 0) {
1359
        goto found_tlb;
1360
    }
1361

    
1362
    if (env->spr[SPR_BOOKE_PID2] &&
1363
        ppcmas_tlb_check(env, tlb, raddr, address,
1364
                         env->spr[SPR_BOOKE_PID2]) >= 0) {
1365
        goto found_tlb;
1366
    }
1367

    
1368
    LOG_SWTLB("%s: TLB entry not found\n", __func__);
1369
    return -1;
1370

    
1371
found_tlb:
1372

    
1373
    if (msr_pr != 0) {
1374
        if (tlb->mas7_3 & MAS3_UR) {
1375
            _prot |= PAGE_READ;
1376
        }
1377
        if (tlb->mas7_3 & MAS3_UW) {
1378
            _prot |= PAGE_WRITE;
1379
        }
1380
        if (tlb->mas7_3 & MAS3_UX) {
1381
            _prot |= PAGE_EXEC;
1382
        }
1383
    } else {
1384
        if (tlb->mas7_3 & MAS3_SR) {
1385
            _prot |= PAGE_READ;
1386
        }
1387
        if (tlb->mas7_3 & MAS3_SW) {
1388
            _prot |= PAGE_WRITE;
1389
        }
1390
        if (tlb->mas7_3 & MAS3_SX) {
1391
            _prot |= PAGE_EXEC;
1392
        }
1393
    }
1394

    
1395
    /* Check the address space and permissions */
1396
    if (access_type == ACCESS_CODE) {
1397
        if (msr_ir != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1398
            LOG_SWTLB("%s: AS doesn't match\n", __func__);
1399
            return -1;
1400
        }
1401

    
1402
        *prot = _prot;
1403
        if (_prot & PAGE_EXEC) {
1404
            LOG_SWTLB("%s: good TLB!\n", __func__);
1405
            return 0;
1406
        }
1407

    
1408
        LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
1409
        ret = -3;
1410
    } else {
1411
        if (msr_dr != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1412
            LOG_SWTLB("%s: AS doesn't match\n", __func__);
1413
            return -1;
1414
        }
1415

    
1416
        *prot = _prot;
1417
        if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
1418
            LOG_SWTLB("%s: found TLB!\n", __func__);
1419
            return 0;
1420
        }
1421

    
1422
        LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
1423
        ret = -2;
1424
    }
1425

    
1426
    return ret;
1427
}
1428

    
1429
static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
1430
                                            target_ulong address, int rw,
1431
                                            int access_type)
1432
{
1433
    ppcmas_tlb_t *tlb;
1434
    target_phys_addr_t raddr;
1435
    int i, j, ret;
1436

    
1437
    ret = -1;
1438
    raddr = (target_phys_addr_t)-1ULL;
1439

    
1440
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1441
        int ways = booke206_tlb_ways(env, i);
1442

    
1443
        for (j = 0; j < ways; j++) {
1444
            tlb = booke206_get_tlbm(env, i, address, j);
1445
            ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
1446
                                        rw, access_type);
1447
            if (ret != -1) {
1448
                goto found_tlb;
1449
            }
1450
        }
1451
    }
1452

    
1453
found_tlb:
1454

    
1455
    if (ret >= 0) {
1456
        ctx->raddr = raddr;
1457
        LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1458
                  " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1459
                  ret);
1460
    } else {
1461
        LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1462
                  " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1463
    }
1464

    
1465
    return ret;
1466
}
1467

    
1468
static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1469
                                 target_ulong eaddr, int rw)
1470
{
1471
    int in_plb, ret;
1472

    
1473
    ctx->raddr = eaddr;
1474
    ctx->prot = PAGE_READ | PAGE_EXEC;
1475
    ret = 0;
1476
    switch (env->mmu_model) {
1477
    case POWERPC_MMU_32B:
1478
    case POWERPC_MMU_601:
1479
    case POWERPC_MMU_SOFT_6xx:
1480
    case POWERPC_MMU_SOFT_74xx:
1481
    case POWERPC_MMU_SOFT_4xx:
1482
    case POWERPC_MMU_REAL:
1483
    case POWERPC_MMU_BOOKE:
1484
        ctx->prot |= PAGE_WRITE;
1485
        break;
1486
#if defined(TARGET_PPC64)
1487
    case POWERPC_MMU_620:
1488
    case POWERPC_MMU_64B:
1489
    case POWERPC_MMU_2_06:
1490
        /* Real address are 60 bits long */
1491
        ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1492
        ctx->prot |= PAGE_WRITE;
1493
        break;
1494
#endif
1495
    case POWERPC_MMU_SOFT_4xx_Z:
1496
        if (unlikely(msr_pe != 0)) {
1497
            /* 403 family add some particular protections,
1498
             * using PBL/PBU registers for accesses with no translation.
1499
             */
1500
            in_plb =
1501
                /* Check PLB validity */
1502
                (env->pb[0] < env->pb[1] &&
1503
                 /* and address in plb area */
1504
                 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1505
                (env->pb[2] < env->pb[3] &&
1506
                 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1507
            if (in_plb ^ msr_px) {
1508
                /* Access in protected area */
1509
                if (rw == 1) {
1510
                    /* Access is not allowed */
1511
                    ret = -2;
1512
                }
1513
            } else {
1514
                /* Read-write access is allowed */
1515
                ctx->prot |= PAGE_WRITE;
1516
            }
1517
        }
1518
        break;
1519
    case POWERPC_MMU_MPC8xx:
1520
        /* XXX: TODO */
1521
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1522
        break;
1523
    case POWERPC_MMU_BOOKE206:
1524
        cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");
1525
        break;
1526
    default:
1527
        cpu_abort(env, "Unknown or invalid MMU model\n");
1528
        return -1;
1529
    }
1530

    
1531
    return ret;
1532
}
1533

    
1534
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1535
                          int rw, int access_type)
1536
{
1537
    int ret;
1538

    
1539
#if 0
1540
    qemu_log("%s\n", __func__);
1541
#endif
1542
    if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1543
        (access_type != ACCESS_CODE && msr_dr == 0)) {
1544
        if (env->mmu_model == POWERPC_MMU_BOOKE) {
1545
            /* The BookE MMU always performs address translation. The
1546
               IS and DS bits only affect the address space.  */
1547
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1548
                                                rw, access_type);
1549
        } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
1550
            ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1551
                                                   access_type);
1552
        } else {
1553
            /* No address translation.  */
1554
            ret = check_physical(env, ctx, eaddr, rw);
1555
        }
1556
    } else {
1557
        ret = -1;
1558
        switch (env->mmu_model) {
1559
        case POWERPC_MMU_32B:
1560
        case POWERPC_MMU_601:
1561
        case POWERPC_MMU_SOFT_6xx:
1562
        case POWERPC_MMU_SOFT_74xx:
1563
            /* Try to find a BAT */
1564
            if (env->nb_BATs != 0)
1565
                ret = get_bat(env, ctx, eaddr, rw, access_type);
1566
#if defined(TARGET_PPC64)
1567
        case POWERPC_MMU_620:
1568
        case POWERPC_MMU_64B:
1569
        case POWERPC_MMU_2_06:
1570
#endif
1571
            if (ret < 0) {
1572
                /* We didn't match any BAT entry or don't have BATs */
1573
                ret = get_segment(env, ctx, eaddr, rw, access_type);
1574
            }
1575
            break;
1576
        case POWERPC_MMU_SOFT_4xx:
1577
        case POWERPC_MMU_SOFT_4xx_Z:
1578
            ret = mmu40x_get_physical_address(env, ctx, eaddr,
1579
                                              rw, access_type);
1580
            break;
1581
        case POWERPC_MMU_BOOKE:
1582
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1583
                                                rw, access_type);
1584
            break;
1585
        case POWERPC_MMU_BOOKE206:
1586
            ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1587
                                               access_type);
1588
            break;
1589
        case POWERPC_MMU_MPC8xx:
1590
            /* XXX: TODO */
1591
            cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1592
            break;
1593
        case POWERPC_MMU_REAL:
1594
            cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1595
            return -1;
1596
        default:
1597
            cpu_abort(env, "Unknown or invalid MMU model\n");
1598
            return -1;
1599
        }
1600
    }
1601
#if 0
1602
    qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1603
             __func__, eaddr, ret, ctx->raddr);
1604
#endif
1605

    
1606
    return ret;
1607
}
1608

    
1609
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1610
{
1611
    mmu_ctx_t ctx;
1612

    
1613
    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1614
        return -1;
1615

    
1616
    return ctx.raddr & TARGET_PAGE_MASK;
1617
}
1618

    
1619
static void booke206_update_mas_tlb_miss(CPUState *env, target_ulong address,
1620
                                     int rw)
1621
{
1622
    env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1623
    env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1624
    env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1625
    env->spr[SPR_BOOKE_MAS3] = 0;
1626
    env->spr[SPR_BOOKE_MAS6] = 0;
1627
    env->spr[SPR_BOOKE_MAS7] = 0;
1628

    
1629
    /* AS */
1630
    if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
1631
        env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1632
        env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1633
    }
1634

    
1635
    env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1636
    env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1637

    
1638
    switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1639
    case MAS4_TIDSELD_PID0:
1640
        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
1641
        break;
1642
    case MAS4_TIDSELD_PID1:
1643
        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
1644
        break;
1645
    case MAS4_TIDSELD_PID2:
1646
        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
1647
        break;
1648
    }
1649

    
1650
    env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1651

    
1652
    /* next victim logic */
1653
    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1654
    env->last_way++;
1655
    env->last_way &= booke206_tlb_ways(env, 0) - 1;
1656
    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1657
}
1658

    
1659
/* Perform address translation */
1660
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1661
                              int mmu_idx)
1662
{
1663
    mmu_ctx_t ctx;
1664
    int access_type;
1665
    int ret = 0;
1666

    
1667
    if (rw == 2) {
1668
        /* code access */
1669
        rw = 0;
1670
        access_type = ACCESS_CODE;
1671
    } else {
1672
        /* data access */
1673
        access_type = env->access_type;
1674
    }
1675
    ret = get_physical_address(env, &ctx, address, rw, access_type);
1676
    if (ret == 0) {
1677
        tlb_set_page(env, address & TARGET_PAGE_MASK,
1678
                     ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1679
                     mmu_idx, TARGET_PAGE_SIZE);
1680
        ret = 0;
1681
    } else if (ret < 0) {
1682
        LOG_MMU_STATE(env);
1683
        if (access_type == ACCESS_CODE) {
1684
            switch (ret) {
1685
            case -1:
1686
                /* No matches in page tables or TLB */
1687
                switch (env->mmu_model) {
1688
                case POWERPC_MMU_SOFT_6xx:
1689
                    env->exception_index = POWERPC_EXCP_IFTLB;
1690
                    env->error_code = 1 << 18;
1691
                    env->spr[SPR_IMISS] = address;
1692
                    env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1693
                    goto tlb_miss;
1694
                case POWERPC_MMU_SOFT_74xx:
1695
                    env->exception_index = POWERPC_EXCP_IFTLB;
1696
                    goto tlb_miss_74xx;
1697
                case POWERPC_MMU_SOFT_4xx:
1698
                case POWERPC_MMU_SOFT_4xx_Z:
1699
                    env->exception_index = POWERPC_EXCP_ITLB;
1700
                    env->error_code = 0;
1701
                    env->spr[SPR_40x_DEAR] = address;
1702
                    env->spr[SPR_40x_ESR] = 0x00000000;
1703
                    break;
1704
                case POWERPC_MMU_32B:
1705
                case POWERPC_MMU_601:
1706
#if defined(TARGET_PPC64)
1707
                case POWERPC_MMU_620:
1708
                case POWERPC_MMU_64B:
1709
                case POWERPC_MMU_2_06:
1710
#endif
1711
                    env->exception_index = POWERPC_EXCP_ISI;
1712
                    env->error_code = 0x40000000;
1713
                    break;
1714
                case POWERPC_MMU_BOOKE206:
1715
                    booke206_update_mas_tlb_miss(env, address, rw);
1716
                    /* fall through */
1717
                case POWERPC_MMU_BOOKE:
1718
                    env->exception_index = POWERPC_EXCP_ITLB;
1719
                    env->error_code = 0;
1720
                    env->spr[SPR_BOOKE_DEAR] = address;
1721
                    return -1;
1722
                case POWERPC_MMU_MPC8xx:
1723
                    /* XXX: TODO */
1724
                    cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1725
                    break;
1726
                case POWERPC_MMU_REAL:
1727
                    cpu_abort(env, "PowerPC in real mode should never raise "
1728
                              "any MMU exceptions\n");
1729
                    return -1;
1730
                default:
1731
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1732
                    return -1;
1733
                }
1734
                break;
1735
            case -2:
1736
                /* Access rights violation */
1737
                env->exception_index = POWERPC_EXCP_ISI;
1738
                env->error_code = 0x08000000;
1739
                break;
1740
            case -3:
1741
                /* No execute protection violation */
1742
                if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1743
                    (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1744
                    env->spr[SPR_BOOKE_ESR] = 0x00000000;
1745
                }
1746
                env->exception_index = POWERPC_EXCP_ISI;
1747
                env->error_code = 0x10000000;
1748
                break;
1749
            case -4:
1750
                /* Direct store exception */
1751
                /* No code fetch is allowed in direct-store areas */
1752
                env->exception_index = POWERPC_EXCP_ISI;
1753
                env->error_code = 0x10000000;
1754
                break;
1755
#if defined(TARGET_PPC64)
1756
            case -5:
1757
                /* No match in segment table */
1758
                if (env->mmu_model == POWERPC_MMU_620) {
1759
                    env->exception_index = POWERPC_EXCP_ISI;
1760
                    /* XXX: this might be incorrect */
1761
                    env->error_code = 0x40000000;
1762
                } else {
1763
                    env->exception_index = POWERPC_EXCP_ISEG;
1764
                    env->error_code = 0;
1765
                }
1766
                break;
1767
#endif
1768
            }
1769
        } else {
1770
            switch (ret) {
1771
            case -1:
1772
                /* No matches in page tables or TLB */
1773
                switch (env->mmu_model) {
1774
                case POWERPC_MMU_SOFT_6xx:
1775
                    if (rw == 1) {
1776
                        env->exception_index = POWERPC_EXCP_DSTLB;
1777
                        env->error_code = 1 << 16;
1778
                    } else {
1779
                        env->exception_index = POWERPC_EXCP_DLTLB;
1780
                        env->error_code = 0;
1781
                    }
1782
                    env->spr[SPR_DMISS] = address;
1783
                    env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1784
                tlb_miss:
1785
                    env->error_code |= ctx.key << 19;
1786
                    env->spr[SPR_HASH1] = env->htab_base +
1787
                        get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1788
                    env->spr[SPR_HASH2] = env->htab_base +
1789
                        get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1790
                    break;
1791
                case POWERPC_MMU_SOFT_74xx:
1792
                    if (rw == 1) {
1793
                        env->exception_index = POWERPC_EXCP_DSTLB;
1794
                    } else {
1795
                        env->exception_index = POWERPC_EXCP_DLTLB;
1796
                    }
1797
                tlb_miss_74xx:
1798
                    /* Implement LRU algorithm */
1799
                    env->error_code = ctx.key << 19;
1800
                    env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1801
                        ((env->last_way + 1) & (env->nb_ways - 1));
1802
                    env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1803
                    break;
1804
                case POWERPC_MMU_SOFT_4xx:
1805
                case POWERPC_MMU_SOFT_4xx_Z:
1806
                    env->exception_index = POWERPC_EXCP_DTLB;
1807
                    env->error_code = 0;
1808
                    env->spr[SPR_40x_DEAR] = address;
1809
                    if (rw)
1810
                        env->spr[SPR_40x_ESR] = 0x00800000;
1811
                    else
1812
                        env->spr[SPR_40x_ESR] = 0x00000000;
1813
                    break;
1814
                case POWERPC_MMU_32B:
1815
                case POWERPC_MMU_601:
1816
#if defined(TARGET_PPC64)
1817
                case POWERPC_MMU_620:
1818
                case POWERPC_MMU_64B:
1819
                case POWERPC_MMU_2_06:
1820
#endif
1821
                    env->exception_index = POWERPC_EXCP_DSI;
1822
                    env->error_code = 0;
1823
                    env->spr[SPR_DAR] = address;
1824
                    if (rw == 1)
1825
                        env->spr[SPR_DSISR] = 0x42000000;
1826
                    else
1827
                        env->spr[SPR_DSISR] = 0x40000000;
1828
                    break;
1829
                case POWERPC_MMU_MPC8xx:
1830
                    /* XXX: TODO */
1831
                    cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1832
                    break;
1833
                case POWERPC_MMU_BOOKE206:
1834
                    booke206_update_mas_tlb_miss(env, address, rw);
1835
                    /* fall through */
1836
                case POWERPC_MMU_BOOKE:
1837
                    env->exception_index = POWERPC_EXCP_DTLB;
1838
                    env->error_code = 0;
1839
                    env->spr[SPR_BOOKE_DEAR] = address;
1840
                    env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1841
                    return -1;
1842
                case POWERPC_MMU_REAL:
1843
                    cpu_abort(env, "PowerPC in real mode should never raise "
1844
                              "any MMU exceptions\n");
1845
                    return -1;
1846
                default:
1847
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1848
                    return -1;
1849
                }
1850
                break;
1851
            case -2:
1852
                /* Access rights violation */
1853
                env->exception_index = POWERPC_EXCP_DSI;
1854
                env->error_code = 0;
1855
                if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1856
                    || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1857
                    env->spr[SPR_40x_DEAR] = address;
1858
                    if (rw) {
1859
                        env->spr[SPR_40x_ESR] |= 0x00800000;
1860
                    }
1861
                } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1862
                           (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1863
                    env->spr[SPR_BOOKE_DEAR] = address;
1864
                    env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1865
                } else {
1866
                    env->spr[SPR_DAR] = address;
1867
                    if (rw == 1) {
1868
                        env->spr[SPR_DSISR] = 0x0A000000;
1869
                    } else {
1870
                        env->spr[SPR_DSISR] = 0x08000000;
1871
                    }
1872
                }
1873
                break;
1874
            case -4:
1875
                /* Direct store exception */
1876
                switch (access_type) {
1877
                case ACCESS_FLOAT:
1878
                    /* Floating point load/store */
1879
                    env->exception_index = POWERPC_EXCP_ALIGN;
1880
                    env->error_code = POWERPC_EXCP_ALIGN_FP;
1881
                    env->spr[SPR_DAR] = address;
1882
                    break;
1883
                case ACCESS_RES:
1884
                    /* lwarx, ldarx or stwcx. */
1885
                    env->exception_index = POWERPC_EXCP_DSI;
1886
                    env->error_code = 0;
1887
                    env->spr[SPR_DAR] = address;
1888
                    if (rw == 1)
1889
                        env->spr[SPR_DSISR] = 0x06000000;
1890
                    else
1891
                        env->spr[SPR_DSISR] = 0x04000000;
1892
                    break;
1893
                case ACCESS_EXT:
1894
                    /* eciwx or ecowx */
1895
                    env->exception_index = POWERPC_EXCP_DSI;
1896
                    env->error_code = 0;
1897
                    env->spr[SPR_DAR] = address;
1898
                    if (rw == 1)
1899
                        env->spr[SPR_DSISR] = 0x06100000;
1900
                    else
1901
                        env->spr[SPR_DSISR] = 0x04100000;
1902
                    break;
1903
                default:
1904
                    printf("DSI: invalid exception (%d)\n", ret);
1905
                    env->exception_index = POWERPC_EXCP_PROGRAM;
1906
                    env->error_code =
1907
                        POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1908
                    env->spr[SPR_DAR] = address;
1909
                    break;
1910
                }
1911
                break;
1912
#if defined(TARGET_PPC64)
1913
            case -5:
1914
                /* No match in segment table */
1915
                if (env->mmu_model == POWERPC_MMU_620) {
1916
                    env->exception_index = POWERPC_EXCP_DSI;
1917
                    env->error_code = 0;
1918
                    env->spr[SPR_DAR] = address;
1919
                    /* XXX: this might be incorrect */
1920
                    if (rw == 1)
1921
                        env->spr[SPR_DSISR] = 0x42000000;
1922
                    else
1923
                        env->spr[SPR_DSISR] = 0x40000000;
1924
                } else {
1925
                    env->exception_index = POWERPC_EXCP_DSEG;
1926
                    env->error_code = 0;
1927
                    env->spr[SPR_DAR] = address;
1928
                }
1929
                break;
1930
#endif
1931
            }
1932
        }
1933
#if 0
1934
        printf("%s: set exception to %d %02x\n", __func__,
1935
               env->exception, env->error_code);
1936
#endif
1937
        ret = 1;
1938
    }
1939

    
1940
    return ret;
1941
}
1942

    
1943
/*****************************************************************************/
1944
/* BATs management */
1945
#if !defined(FLUSH_ALL_TLBS)
1946
static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1947
                                     target_ulong mask)
1948
{
1949
    target_ulong base, end, page;
1950

    
1951
    base = BATu & ~0x0001FFFF;
1952
    end = base + mask + 0x00020000;
1953
    LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1954
             TARGET_FMT_lx ")\n", base, end, mask);
1955
    for (page = base; page != end; page += TARGET_PAGE_SIZE)
1956
        tlb_flush_page(env, page);
1957
    LOG_BATS("Flush done\n");
1958
}
1959
#endif
1960

    
1961
static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1962
                                  target_ulong value)
1963
{
1964
    LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1965
             nr, ul == 0 ? 'u' : 'l', value, env->nip);
1966
}
1967

    
1968
void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1969
{
1970
    target_ulong mask;
1971

    
1972
    dump_store_bat(env, 'I', 0, nr, value);
1973
    if (env->IBAT[0][nr] != value) {
1974
        mask = (value << 15) & 0x0FFE0000UL;
1975
#if !defined(FLUSH_ALL_TLBS)
1976
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1977
#endif
1978
        /* When storing valid upper BAT, mask BEPI and BRPN
1979
         * and invalidate all TLBs covered by this BAT
1980
         */
1981
        mask = (value << 15) & 0x0FFE0000UL;
1982
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1983
            (value & ~0x0001FFFFUL & ~mask);
1984
        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1985
            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1986
#if !defined(FLUSH_ALL_TLBS)
1987
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1988
#else
1989
        tlb_flush(env, 1);
1990
#endif
1991
    }
1992
}
1993

    
1994
void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1995
{
1996
    dump_store_bat(env, 'I', 1, nr, value);
1997
    env->IBAT[1][nr] = value;
1998
}
1999

    
2000
void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
2001
{
2002
    target_ulong mask;
2003

    
2004
    dump_store_bat(env, 'D', 0, nr, value);
2005
    if (env->DBAT[0][nr] != value) {
2006
        /* When storing valid upper BAT, mask BEPI and BRPN
2007
         * and invalidate all TLBs covered by this BAT
2008
         */
2009
        mask = (value << 15) & 0x0FFE0000UL;
2010
#if !defined(FLUSH_ALL_TLBS)
2011
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
2012
#endif
2013
        mask = (value << 15) & 0x0FFE0000UL;
2014
        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
2015
            (value & ~0x0001FFFFUL & ~mask);
2016
        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
2017
            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
2018
#if !defined(FLUSH_ALL_TLBS)
2019
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
2020
#else
2021
        tlb_flush(env, 1);
2022
#endif
2023
    }
2024
}
2025

    
2026
void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
2027
{
2028
    dump_store_bat(env, 'D', 1, nr, value);
2029
    env->DBAT[1][nr] = value;
2030
}
2031

    
2032
void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
2033
{
2034
    target_ulong mask;
2035
#if defined(FLUSH_ALL_TLBS)
2036
    int do_inval;
2037
#endif
2038

    
2039
    dump_store_bat(env, 'I', 0, nr, value);
2040
    if (env->IBAT[0][nr] != value) {
2041
#if defined(FLUSH_ALL_TLBS)
2042
        do_inval = 0;
2043
#endif
2044
        mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
2045
        if (env->IBAT[1][nr] & 0x40) {
2046
            /* Invalidate BAT only if it is valid */
2047
#if !defined(FLUSH_ALL_TLBS)
2048
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2049
#else
2050
            do_inval = 1;
2051
#endif
2052
        }
2053
        /* When storing valid upper BAT, mask BEPI and BRPN
2054
         * and invalidate all TLBs covered by this BAT
2055
         */
2056
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
2057
            (value & ~0x0001FFFFUL & ~mask);
2058
        env->DBAT[0][nr] = env->IBAT[0][nr];
2059
        if (env->IBAT[1][nr] & 0x40) {
2060
#if !defined(FLUSH_ALL_TLBS)
2061
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2062
#else
2063
            do_inval = 1;
2064
#endif
2065
        }
2066
#if defined(FLUSH_ALL_TLBS)
2067
        if (do_inval)
2068
            tlb_flush(env, 1);
2069
#endif
2070
    }
2071
}
2072

    
2073
void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
2074
{
2075
    target_ulong mask;
2076
#if defined(FLUSH_ALL_TLBS)
2077
    int do_inval;
2078
#endif
2079

    
2080
    dump_store_bat(env, 'I', 1, nr, value);
2081
    if (env->IBAT[1][nr] != value) {
2082
#if defined(FLUSH_ALL_TLBS)
2083
        do_inval = 0;
2084
#endif
2085
        if (env->IBAT[1][nr] & 0x40) {
2086
#if !defined(FLUSH_ALL_TLBS)
2087
            mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
2088
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2089
#else
2090
            do_inval = 1;
2091
#endif
2092
        }
2093
        if (value & 0x40) {
2094
#if !defined(FLUSH_ALL_TLBS)
2095
            mask = (value << 17) & 0x0FFE0000UL;
2096
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2097
#else
2098
            do_inval = 1;
2099
#endif
2100
        }
2101
        env->IBAT[1][nr] = value;
2102
        env->DBAT[1][nr] = value;
2103
#if defined(FLUSH_ALL_TLBS)
2104
        if (do_inval)
2105
            tlb_flush(env, 1);
2106
#endif
2107
    }
2108
}
2109

    
2110
/*****************************************************************************/
2111
/* TLB management */
2112
void ppc_tlb_invalidate_all (CPUPPCState *env)
2113
{
2114
    switch (env->mmu_model) {
2115
    case POWERPC_MMU_SOFT_6xx:
2116
    case POWERPC_MMU_SOFT_74xx:
2117
        ppc6xx_tlb_invalidate_all(env);
2118
        break;
2119
    case POWERPC_MMU_SOFT_4xx:
2120
    case POWERPC_MMU_SOFT_4xx_Z:
2121
        ppc4xx_tlb_invalidate_all(env);
2122
        break;
2123
    case POWERPC_MMU_REAL:
2124
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2125
        break;
2126
    case POWERPC_MMU_MPC8xx:
2127
        /* XXX: TODO */
2128
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2129
        break;
2130
    case POWERPC_MMU_BOOKE:
2131
        tlb_flush(env, 1);
2132
        break;
2133
    case POWERPC_MMU_BOOKE206:
2134
        booke206_flush_tlb(env, -1, 0);
2135
        break;
2136
    case POWERPC_MMU_32B:
2137
    case POWERPC_MMU_601:
2138
#if defined(TARGET_PPC64)
2139
    case POWERPC_MMU_620:
2140
    case POWERPC_MMU_64B:
2141
    case POWERPC_MMU_2_06:
2142
#endif /* defined(TARGET_PPC64) */
2143
        tlb_flush(env, 1);
2144
        break;
2145
    default:
2146
        /* XXX: TODO */
2147
        cpu_abort(env, "Unknown MMU model\n");
2148
        break;
2149
    }
2150
}
2151

    
2152
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
2153
{
2154
#if !defined(FLUSH_ALL_TLBS)
2155
    addr &= TARGET_PAGE_MASK;
2156
    switch (env->mmu_model) {
2157
    case POWERPC_MMU_SOFT_6xx:
2158
    case POWERPC_MMU_SOFT_74xx:
2159
        ppc6xx_tlb_invalidate_virt(env, addr, 0);
2160
        if (env->id_tlbs == 1)
2161
            ppc6xx_tlb_invalidate_virt(env, addr, 1);
2162
        break;
2163
    case POWERPC_MMU_SOFT_4xx:
2164
    case POWERPC_MMU_SOFT_4xx_Z:
2165
        ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
2166
        break;
2167
    case POWERPC_MMU_REAL:
2168
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2169
        break;
2170
    case POWERPC_MMU_MPC8xx:
2171
        /* XXX: TODO */
2172
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2173
        break;
2174
    case POWERPC_MMU_BOOKE:
2175
        /* XXX: TODO */
2176
        cpu_abort(env, "BookE MMU model is not implemented\n");
2177
        break;
2178
    case POWERPC_MMU_BOOKE206:
2179
        /* XXX: TODO */
2180
        cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
2181
        break;
2182
    case POWERPC_MMU_32B:
2183
    case POWERPC_MMU_601:
2184
        /* tlbie invalidate TLBs for all segments */
2185
        addr &= ~((target_ulong)-1ULL << 28);
2186
        /* XXX: this case should be optimized,
2187
         * giving a mask to tlb_flush_page
2188
         */
2189
        tlb_flush_page(env, addr | (0x0 << 28));
2190
        tlb_flush_page(env, addr | (0x1 << 28));
2191
        tlb_flush_page(env, addr | (0x2 << 28));
2192
        tlb_flush_page(env, addr | (0x3 << 28));
2193
        tlb_flush_page(env, addr | (0x4 << 28));
2194
        tlb_flush_page(env, addr | (0x5 << 28));
2195
        tlb_flush_page(env, addr | (0x6 << 28));
2196
        tlb_flush_page(env, addr | (0x7 << 28));
2197
        tlb_flush_page(env, addr | (0x8 << 28));
2198
        tlb_flush_page(env, addr | (0x9 << 28));
2199
        tlb_flush_page(env, addr | (0xA << 28));
2200
        tlb_flush_page(env, addr | (0xB << 28));
2201
        tlb_flush_page(env, addr | (0xC << 28));
2202
        tlb_flush_page(env, addr | (0xD << 28));
2203
        tlb_flush_page(env, addr | (0xE << 28));
2204
        tlb_flush_page(env, addr | (0xF << 28));
2205
        break;
2206
#if defined(TARGET_PPC64)
2207
    case POWERPC_MMU_620:
2208
    case POWERPC_MMU_64B:
2209
    case POWERPC_MMU_2_06:
2210
        /* tlbie invalidate TLBs for all segments */
2211
        /* XXX: given the fact that there are too many segments to invalidate,
2212
         *      and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
2213
         *      we just invalidate all TLBs
2214
         */
2215
        tlb_flush(env, 1);
2216
        break;
2217
#endif /* defined(TARGET_PPC64) */
2218
    default:
2219
        /* XXX: TODO */
2220
        cpu_abort(env, "Unknown MMU model\n");
2221
        break;
2222
    }
2223
#else
2224
    ppc_tlb_invalidate_all(env);
2225
#endif
2226
}
2227

    
2228
/*****************************************************************************/
2229
/* Special registers manipulation */
2230
#if defined(TARGET_PPC64)
2231
void ppc_store_asr (CPUPPCState *env, target_ulong value)
2232
{
2233
    if (env->asr != value) {
2234
        env->asr = value;
2235
        tlb_flush(env, 1);
2236
    }
2237
}
2238
#endif
2239

    
2240
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
2241
{
2242
    LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
2243
    if (env->spr[SPR_SDR1] != value) {
2244
        env->spr[SPR_SDR1] = value;
2245
#if defined(TARGET_PPC64)
2246
        if (env->mmu_model & POWERPC_MMU_64) {
2247
            target_ulong htabsize = value & SDR_64_HTABSIZE;
2248

    
2249
            if (htabsize > 28) {
2250
                fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2251
                        " stored in SDR1\n", htabsize);
2252
                htabsize = 28;
2253
            }
2254
            env->htab_mask = (1ULL << (htabsize + 18)) - 1;
2255
            env->htab_base = value & SDR_64_HTABORG;
2256
        } else
2257
#endif /* defined(TARGET_PPC64) */
2258
        {
2259
            /* FIXME: Should check for valid HTABMASK values */
2260
            env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
2261
            env->htab_base = value & SDR_32_HTABORG;
2262
        }
2263
        tlb_flush(env, 1);
2264
    }
2265
}
2266

    
2267
#if defined(TARGET_PPC64)
2268
target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
2269
{
2270
    // XXX
2271
    return 0;
2272
}
2273
#endif
2274

    
2275
void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
2276
{
2277
    LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2278
            srnum, value, env->sr[srnum]);
2279
#if defined(TARGET_PPC64)
2280
    if (env->mmu_model & POWERPC_MMU_64) {
2281
        uint64_t rb = 0, rs = 0;
2282

    
2283
        /* ESID = srnum */
2284
        rb |= ((uint32_t)srnum & 0xf) << 28;
2285
        /* Set the valid bit */
2286
        rb |= 1 << 27;
2287
        /* Index = ESID */
2288
        rb |= (uint32_t)srnum;
2289

    
2290
        /* VSID = VSID */
2291
        rs |= (value & 0xfffffff) << 12;
2292
        /* flags = flags */
2293
        rs |= ((value >> 27) & 0xf) << 8;
2294

    
2295
        ppc_store_slb(env, rb, rs);
2296
    } else
2297
#endif
2298
    if (env->sr[srnum] != value) {
2299
        env->sr[srnum] = value;
2300
/* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2301
   flusing the whole TLB. */
2302
#if !defined(FLUSH_ALL_TLBS) && 0
2303
        {
2304
            target_ulong page, end;
2305
            /* Invalidate 256 MB of virtual memory */
2306
            page = (16 << 20) * srnum;
2307
            end = page + (16 << 20);
2308
            for (; page != end; page += TARGET_PAGE_SIZE)
2309
                tlb_flush_page(env, page);
2310
        }
2311
#else
2312
        tlb_flush(env, 1);
2313
#endif
2314
    }
2315
}
2316
#endif /* !defined (CONFIG_USER_ONLY) */
2317

    
2318
/* GDBstub can read and write MSR... */
2319
void ppc_store_msr (CPUPPCState *env, target_ulong value)
2320
{
2321
    hreg_store_msr(env, value, 0);
2322
}
2323

    
2324
/*****************************************************************************/
2325
/* Exception processing */
2326
#if defined (CONFIG_USER_ONLY)
2327
void do_interrupt (CPUState *env)
2328
{
2329
    env->exception_index = POWERPC_EXCP_NONE;
2330
    env->error_code = 0;
2331
}
2332

    
2333
void ppc_hw_interrupt (CPUState *env)
2334
{
2335
    env->exception_index = POWERPC_EXCP_NONE;
2336
    env->error_code = 0;
2337
}
2338
#else /* defined (CONFIG_USER_ONLY) */
2339
static inline void dump_syscall(CPUState *env)
2340
{
2341
    qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2342
                  " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2343
                  " nip=" TARGET_FMT_lx "\n",
2344
                  ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2345
                  ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2346
                  ppc_dump_gpr(env, 6), env->nip);
2347
}
2348

    
2349
/* Note that this function should be greatly optimized
2350
 * when called with a constant excp, from ppc_hw_interrupt
2351
 */
2352
static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2353
{
2354
    target_ulong msr, new_msr, vector;
2355
    int srr0, srr1, asrr0, asrr1;
2356
    int lpes0, lpes1, lev;
2357

    
2358
    if (0) {
2359
        /* XXX: find a suitable condition to enable the hypervisor mode */
2360
        lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2361
        lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2362
    } else {
2363
        /* Those values ensure we won't enter the hypervisor mode */
2364
        lpes0 = 0;
2365
        lpes1 = 1;
2366
    }
2367

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

    
2371
    /* new srr1 value excluding must-be-zero bits */
2372
    msr = env->msr & ~0x783f0000ULL;
2373

    
2374
    /* new interrupt handler msr */
2375
    new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2376

    
2377
    /* target registers */
2378
    srr0 = SPR_SRR0;
2379
    srr1 = SPR_SRR1;
2380
    asrr0 = -1;
2381
    asrr1 = -1;
2382

    
2383
    switch (excp) {
2384
    case POWERPC_EXCP_NONE:
2385
        /* Should never happen */
2386
        return;
2387
    case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
2388
        switch (excp_model) {
2389
        case POWERPC_EXCP_40x:
2390
            srr0 = SPR_40x_SRR2;
2391
            srr1 = SPR_40x_SRR3;
2392
            break;
2393
        case POWERPC_EXCP_BOOKE:
2394
            srr0 = SPR_BOOKE_CSRR0;
2395
            srr1 = SPR_BOOKE_CSRR1;
2396
            break;
2397
        case POWERPC_EXCP_G2:
2398
            break;
2399
        default:
2400
            goto excp_invalid;
2401
        }
2402
        goto store_next;
2403
    case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
2404
        if (msr_me == 0) {
2405
            /* Machine check exception is not enabled.
2406
             * Enter checkstop state.
2407
             */
2408
            if (qemu_log_enabled()) {
2409
                qemu_log("Machine check while not allowed. "
2410
                        "Entering checkstop state\n");
2411
            } else {
2412
                fprintf(stderr, "Machine check while not allowed. "
2413
                        "Entering checkstop state\n");
2414
            }
2415
            env->halted = 1;
2416
            env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2417
        }
2418
        if (0) {
2419
            /* XXX: find a suitable condition to enable the hypervisor mode */
2420
            new_msr |= (target_ulong)MSR_HVB;
2421
        }
2422

    
2423
        /* machine check exceptions don't have ME set */
2424
        new_msr &= ~((target_ulong)1 << MSR_ME);
2425

    
2426
        /* XXX: should also have something loaded in DAR / DSISR */
2427
        switch (excp_model) {
2428
        case POWERPC_EXCP_40x:
2429
            srr0 = SPR_40x_SRR2;
2430
            srr1 = SPR_40x_SRR3;
2431
            break;
2432
        case POWERPC_EXCP_BOOKE:
2433
            srr0 = SPR_BOOKE_MCSRR0;
2434
            srr1 = SPR_BOOKE_MCSRR1;
2435
            asrr0 = SPR_BOOKE_CSRR0;
2436
            asrr1 = SPR_BOOKE_CSRR1;
2437
            break;
2438
        default:
2439
            break;
2440
        }
2441
        goto store_next;
2442
    case POWERPC_EXCP_DSI:       /* Data storage exception                   */
2443
        LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2444
                 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2445
        if (lpes1 == 0)
2446
            new_msr |= (target_ulong)MSR_HVB;
2447
        goto store_next;
2448
    case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
2449
        LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2450
                 "\n", msr, env->nip);
2451
        if (lpes1 == 0)
2452
            new_msr |= (target_ulong)MSR_HVB;
2453
        msr |= env->error_code;
2454
        goto store_next;
2455
    case POWERPC_EXCP_EXTERNAL:  /* External input                           */
2456
        if (lpes0 == 1)
2457
            new_msr |= (target_ulong)MSR_HVB;
2458
        goto store_next;
2459
    case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
2460
        if (lpes1 == 0)
2461
            new_msr |= (target_ulong)MSR_HVB;
2462
        /* XXX: this is false */
2463
        /* Get rS/rD and rA from faulting opcode */
2464
        env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2465
        goto store_current;
2466
    case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
2467
        switch (env->error_code & ~0xF) {
2468
        case POWERPC_EXCP_FP:
2469
            if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2470
                LOG_EXCP("Ignore floating point exception\n");
2471
                env->exception_index = POWERPC_EXCP_NONE;
2472
                env->error_code = 0;
2473
                return;
2474
            }
2475
            if (lpes1 == 0)
2476
                new_msr |= (target_ulong)MSR_HVB;
2477
            msr |= 0x00100000;
2478
            if (msr_fe0 == msr_fe1)
2479
                goto store_next;
2480
            msr |= 0x00010000;
2481
            break;
2482
        case POWERPC_EXCP_INVAL:
2483
            LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2484
            if (lpes1 == 0)
2485
                new_msr |= (target_ulong)MSR_HVB;
2486
            msr |= 0x00080000;
2487
            break;
2488
        case POWERPC_EXCP_PRIV:
2489
            if (lpes1 == 0)
2490
                new_msr |= (target_ulong)MSR_HVB;
2491
            msr |= 0x00040000;
2492
            break;
2493
        case POWERPC_EXCP_TRAP:
2494
            if (lpes1 == 0)
2495
                new_msr |= (target_ulong)MSR_HVB;
2496
            msr |= 0x00020000;
2497
            break;
2498
        default:
2499
            /* Should never occur */
2500
            cpu_abort(env, "Invalid program exception %d. Aborting\n",
2501
                      env->error_code);
2502
            break;
2503
        }
2504
        goto store_current;
2505
    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
2506
        if (lpes1 == 0)
2507
            new_msr |= (target_ulong)MSR_HVB;
2508
        goto store_current;
2509
    case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
2510
        dump_syscall(env);
2511
        lev = env->error_code;
2512
        if ((lev == 1) && cpu_ppc_hypercall) {
2513
            cpu_ppc_hypercall(env);
2514
            return;
2515
        }
2516
        if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2517
            new_msr |= (target_ulong)MSR_HVB;
2518
        goto store_next;
2519
    case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
2520
        goto store_current;
2521
    case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
2522
        if (lpes1 == 0)
2523
            new_msr |= (target_ulong)MSR_HVB;
2524
        goto store_next;
2525
    case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
2526
        /* FIT on 4xx */
2527
        LOG_EXCP("FIT exception\n");
2528
        goto store_next;
2529
    case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
2530
        LOG_EXCP("WDT exception\n");
2531
        switch (excp_model) {
2532
        case POWERPC_EXCP_BOOKE:
2533
            srr0 = SPR_BOOKE_CSRR0;
2534
            srr1 = SPR_BOOKE_CSRR1;
2535
            break;
2536
        default:
2537
            break;
2538
        }
2539
        goto store_next;
2540
    case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
2541
        goto store_next;
2542
    case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
2543
        goto store_next;
2544
    case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
2545
        switch (excp_model) {
2546
        case POWERPC_EXCP_BOOKE:
2547
            srr0 = SPR_BOOKE_DSRR0;
2548
            srr1 = SPR_BOOKE_DSRR1;
2549
            asrr0 = SPR_BOOKE_CSRR0;
2550
            asrr1 = SPR_BOOKE_CSRR1;
2551
            break;
2552
        default:
2553
            break;
2554
        }
2555
        /* XXX: TODO */
2556
        cpu_abort(env, "Debug exception is not implemented yet !\n");
2557
        goto store_next;
2558
    case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
2559
        goto store_current;
2560
    case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
2561
        /* XXX: TODO */
2562
        cpu_abort(env, "Embedded floating point data exception "
2563
                  "is not implemented yet !\n");
2564
        goto store_next;
2565
    case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
2566
        /* XXX: TODO */
2567
        cpu_abort(env, "Embedded floating point round exception "
2568
                  "is not implemented yet !\n");
2569
        goto store_next;
2570
    case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
2571
        /* XXX: TODO */
2572
        cpu_abort(env,
2573
                  "Performance counter exception is not implemented yet !\n");
2574
        goto store_next;
2575
    case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
2576
        /* XXX: TODO */
2577
        cpu_abort(env,
2578
                  "Embedded doorbell interrupt is not implemented yet !\n");
2579
        goto store_next;
2580
    case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
2581
        switch (excp_model) {
2582
        case POWERPC_EXCP_BOOKE:
2583
            srr0 = SPR_BOOKE_CSRR0;
2584
            srr1 = SPR_BOOKE_CSRR1;
2585
            break;
2586
        default:
2587
            break;
2588
        }
2589
        /* XXX: TODO */
2590
        cpu_abort(env, "Embedded doorbell critical interrupt "
2591
                  "is not implemented yet !\n");
2592
        goto store_next;
2593
    case POWERPC_EXCP_RESET:     /* System reset exception                   */
2594
        if (msr_pow) {
2595
            /* indicate that we resumed from power save mode */
2596
            msr |= 0x10000;
2597
        } else {
2598
            new_msr &= ~((target_ulong)1 << MSR_ME);
2599
        }
2600

    
2601
        if (0) {
2602
            /* XXX: find a suitable condition to enable the hypervisor mode */
2603
            new_msr |= (target_ulong)MSR_HVB;
2604
        }
2605
        goto store_next;
2606
    case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
2607
        if (lpes1 == 0)
2608
            new_msr |= (target_ulong)MSR_HVB;
2609
        goto store_next;
2610
    case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
2611
        if (lpes1 == 0)
2612
            new_msr |= (target_ulong)MSR_HVB;
2613
        goto store_next;
2614
    case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
2615
        srr0 = SPR_HSRR0;
2616
        srr1 = SPR_HSRR1;
2617
        new_msr |= (target_ulong)MSR_HVB;
2618
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2619
        goto store_next;
2620
    case POWERPC_EXCP_TRACE:     /* Trace exception                          */
2621
        if (lpes1 == 0)
2622
            new_msr |= (target_ulong)MSR_HVB;
2623
        goto store_next;
2624
    case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
2625
        srr0 = SPR_HSRR0;
2626
        srr1 = SPR_HSRR1;
2627
        new_msr |= (target_ulong)MSR_HVB;
2628
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2629
        goto store_next;
2630
    case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
2631
        srr0 = SPR_HSRR0;
2632
        srr1 = SPR_HSRR1;
2633
        new_msr |= (target_ulong)MSR_HVB;
2634
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2635
        goto store_next;
2636
    case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
2637
        srr0 = SPR_HSRR0;
2638
        srr1 = SPR_HSRR1;
2639
        new_msr |= (target_ulong)MSR_HVB;
2640
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2641
        goto store_next;
2642
    case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
2643
        srr0 = SPR_HSRR0;
2644
        srr1 = SPR_HSRR1;
2645
        new_msr |= (target_ulong)MSR_HVB;
2646
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2647
        goto store_next;
2648
    case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
2649
        if (lpes1 == 0)
2650
            new_msr |= (target_ulong)MSR_HVB;
2651
        goto store_current;
2652
    case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
2653
        LOG_EXCP("PIT exception\n");
2654
        goto store_next;
2655
    case POWERPC_EXCP_IO:        /* IO error exception                       */
2656
        /* XXX: TODO */
2657
        cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2658
        goto store_next;
2659
    case POWERPC_EXCP_RUNM:      /* Run mode exception                       */
2660
        /* XXX: TODO */
2661
        cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2662
        goto store_next;
2663
    case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 */
2664
        /* XXX: TODO */
2665
        cpu_abort(env, "602 emulation trap exception "
2666
                  "is not implemented yet !\n");
2667
        goto store_next;
2668
    case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
2669
        if (lpes1 == 0) /* XXX: check this */
2670
            new_msr |= (target_ulong)MSR_HVB;
2671
        switch (excp_model) {
2672
        case POWERPC_EXCP_602:
2673
        case POWERPC_EXCP_603:
2674
        case POWERPC_EXCP_603E:
2675
        case POWERPC_EXCP_G2:
2676
            goto tlb_miss_tgpr;
2677
        case POWERPC_EXCP_7x5:
2678
            goto tlb_miss;
2679
        case POWERPC_EXCP_74xx:
2680
            goto tlb_miss_74xx;
2681
        default:
2682
            cpu_abort(env, "Invalid instruction TLB miss exception\n");
2683
            break;
2684
        }
2685
        break;
2686
    case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
2687
        if (lpes1 == 0) /* XXX: check this */
2688
            new_msr |= (target_ulong)MSR_HVB;
2689
        switch (excp_model) {
2690
        case POWERPC_EXCP_602:
2691
        case POWERPC_EXCP_603:
2692
        case POWERPC_EXCP_603E:
2693
        case POWERPC_EXCP_G2:
2694
            goto tlb_miss_tgpr;
2695
        case POWERPC_EXCP_7x5:
2696
            goto tlb_miss;
2697
        case POWERPC_EXCP_74xx:
2698
            goto tlb_miss_74xx;
2699
        default:
2700
            cpu_abort(env, "Invalid data load TLB miss exception\n");
2701
            break;
2702
        }
2703
        break;
2704
    case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
2705
        if (lpes1 == 0) /* XXX: check this */
2706
            new_msr |= (target_ulong)MSR_HVB;
2707
        switch (excp_model) {
2708
        case POWERPC_EXCP_602:
2709
        case POWERPC_EXCP_603:
2710
        case POWERPC_EXCP_603E:
2711
        case POWERPC_EXCP_G2:
2712
        tlb_miss_tgpr:
2713
            /* Swap temporary saved registers with GPRs */
2714
            if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2715
                new_msr |= (target_ulong)1 << MSR_TGPR;
2716
                hreg_swap_gpr_tgpr(env);
2717
            }
2718
            goto tlb_miss;
2719
        case POWERPC_EXCP_7x5:
2720
        tlb_miss:
2721
#if defined (DEBUG_SOFTWARE_TLB)
2722
            if (qemu_log_enabled()) {
2723
                const char *es;
2724
                target_ulong *miss, *cmp;
2725
                int en;
2726
                if (excp == POWERPC_EXCP_IFTLB) {
2727
                    es = "I";
2728
                    en = 'I';
2729
                    miss = &env->spr[SPR_IMISS];
2730
                    cmp = &env->spr[SPR_ICMP];
2731
                } else {
2732
                    if (excp == POWERPC_EXCP_DLTLB)
2733
                        es = "DL";
2734
                    else
2735
                        es = "DS";
2736
                    en = 'D';
2737
                    miss = &env->spr[SPR_DMISS];
2738
                    cmp = &env->spr[SPR_DCMP];
2739
                }
2740
                qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2741
                         TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2742
                         TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2743
                         env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2744
                         env->error_code);
2745
            }
2746
#endif
2747
            msr |= env->crf[0] << 28;
2748
            msr |= env->error_code; /* key, D/I, S/L bits */
2749
            /* Set way using a LRU mechanism */
2750
            msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2751
            break;
2752
        case POWERPC_EXCP_74xx:
2753
        tlb_miss_74xx:
2754
#if defined (DEBUG_SOFTWARE_TLB)
2755
            if (qemu_log_enabled()) {
2756
                const char *es;
2757
                target_ulong *miss, *cmp;
2758
                int en;
2759
                if (excp == POWERPC_EXCP_IFTLB) {
2760
                    es = "I";
2761
                    en = 'I';
2762
                    miss = &env->spr[SPR_TLBMISS];
2763
                    cmp = &env->spr[SPR_PTEHI];
2764
                } else {
2765
                    if (excp == POWERPC_EXCP_DLTLB)
2766
                        es = "DL";
2767
                    else
2768
                        es = "DS";
2769
                    en = 'D';
2770
                    miss = &env->spr[SPR_TLBMISS];
2771
                    cmp = &env->spr[SPR_PTEHI];
2772
                }
2773
                qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2774
                         TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2775
                         env->error_code);
2776
            }
2777
#endif
2778
            msr |= env->error_code; /* key bit */
2779
            break;
2780
        default:
2781
            cpu_abort(env, "Invalid data store TLB miss exception\n");
2782
            break;
2783
        }
2784
        goto store_next;
2785
    case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
2786
        /* XXX: TODO */
2787
        cpu_abort(env, "Floating point assist exception "
2788
                  "is not implemented yet !\n");
2789
        goto store_next;
2790
    case POWERPC_EXCP_DABR:      /* Data address breakpoint                  */
2791
        /* XXX: TODO */
2792
        cpu_abort(env, "DABR exception is not implemented yet !\n");
2793
        goto store_next;
2794
    case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
2795
        /* XXX: TODO */
2796
        cpu_abort(env, "IABR exception is not implemented yet !\n");
2797
        goto store_next;
2798
    case POWERPC_EXCP_SMI:       /* System management interrupt              */
2799
        /* XXX: TODO */
2800
        cpu_abort(env, "SMI exception is not implemented yet !\n");
2801
        goto store_next;
2802
    case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
2803
        /* XXX: TODO */
2804
        cpu_abort(env, "Thermal management exception "
2805
                  "is not implemented yet !\n");
2806
        goto store_next;
2807
    case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
2808
        if (lpes1 == 0)
2809
            new_msr |= (target_ulong)MSR_HVB;
2810
        /* XXX: TODO */
2811
        cpu_abort(env,
2812
                  "Performance counter exception is not implemented yet !\n");
2813
        goto store_next;
2814
    case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
2815
        /* XXX: TODO */
2816
        cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2817
        goto store_next;
2818
    case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
2819
        /* XXX: TODO */
2820
        cpu_abort(env,
2821
                  "970 soft-patch exception is not implemented yet !\n");
2822
        goto store_next;
2823
    case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
2824
        /* XXX: TODO */
2825
        cpu_abort(env,
2826
                  "970 maintenance exception is not implemented yet !\n");
2827
        goto store_next;
2828
    case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             */
2829
        /* XXX: TODO */
2830
        cpu_abort(env, "Maskable external exception "
2831
                  "is not implemented yet !\n");
2832
        goto store_next;
2833
    case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         */
2834
        /* XXX: TODO */
2835
        cpu_abort(env, "Non maskable external exception "
2836
                  "is not implemented yet !\n");
2837
        goto store_next;
2838
    default:
2839
    excp_invalid:
2840
        cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2841
        break;
2842
    store_current:
2843
        /* save current instruction location */
2844
        env->spr[srr0] = env->nip - 4;
2845
        break;
2846
    store_next:
2847
        /* save next instruction location */
2848
        env->spr[srr0] = env->nip;
2849
        break;
2850
    }
2851
    /* Save MSR */
2852
    env->spr[srr1] = msr;
2853
    /* If any alternate SRR register are defined, duplicate saved values */
2854
    if (asrr0 != -1)
2855
        env->spr[asrr0] = env->spr[srr0];
2856
    if (asrr1 != -1)
2857
        env->spr[asrr1] = env->spr[srr1];
2858
    /* If we disactivated any translation, flush TLBs */
2859
    if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2860
        tlb_flush(env, 1);
2861

    
2862
    if (msr_ile) {
2863
        new_msr |= (target_ulong)1 << MSR_LE;
2864
    }
2865

    
2866
    /* Jump to handler */
2867
    vector = env->excp_vectors[excp];
2868
    if (vector == (target_ulong)-1ULL) {
2869
        cpu_abort(env, "Raised an exception without defined vector %d\n",
2870
                  excp);
2871
    }
2872
    vector |= env->excp_prefix;
2873
#if defined(TARGET_PPC64)
2874
    if (excp_model == POWERPC_EXCP_BOOKE) {
2875
        if (!msr_icm) {
2876
            vector = (uint32_t)vector;
2877
        } else {
2878
            new_msr |= (target_ulong)1 << MSR_CM;
2879
        }
2880
    } else {
2881
        if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2882
            vector = (uint32_t)vector;
2883
        } else {
2884
            new_msr |= (target_ulong)1 << MSR_SF;
2885
        }
2886
    }
2887
#endif
2888
    /* XXX: we don't use hreg_store_msr here as already have treated
2889
     *      any special case that could occur. Just store MSR and update hflags
2890
     */
2891
    env->msr = new_msr & env->msr_mask;
2892
    hreg_compute_hflags(env);
2893
    env->nip = vector;
2894
    /* Reset exception state */
2895
    env->exception_index = POWERPC_EXCP_NONE;
2896
    env->error_code = 0;
2897

    
2898
    if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
2899
        (env->mmu_model == POWERPC_MMU_BOOKE206)) {
2900
        /* XXX: The BookE changes address space when switching modes,
2901
                we should probably implement that as different MMU indexes,
2902
                but for the moment we do it the slow way and flush all.  */
2903
        tlb_flush(env, 1);
2904
    }
2905
}
2906

    
2907
void do_interrupt (CPUState *env)
2908
{
2909
    powerpc_excp(env, env->excp_model, env->exception_index);
2910
}
2911

    
2912
void ppc_hw_interrupt (CPUPPCState *env)
2913
{
2914
    int hdice;
2915

    
2916
#if 0
2917
    qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
2918
                __func__, env, env->pending_interrupts,
2919
                env->interrupt_request, (int)msr_me, (int)msr_ee);
2920
#endif
2921
    /* External reset */
2922
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
2923
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
2924
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
2925
        return;
2926
    }
2927
    /* Machine check exception */
2928
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
2929
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
2930
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
2931
        return;
2932
    }
2933
#if 0 /* TODO */
2934
    /* External debug exception */
2935
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
2936
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2937
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
2938
        return;
2939
    }
2940
#endif
2941
    if (0) {
2942
        /* XXX: find a suitable condition to enable the hypervisor mode */
2943
        hdice = env->spr[SPR_LPCR] & 1;
2944
    } else {
2945
        hdice = 0;
2946
    }
2947
    if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
2948
        /* Hypervisor decrementer exception */
2949
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
2950
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
2951
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
2952
            return;
2953
        }
2954
    }
2955
    if (msr_ce != 0) {
2956
        /* External critical interrupt */
2957
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
2958
            /* Taking a critical external interrupt does not clear the external
2959
             * critical interrupt status
2960
             */
2961
#if 0
2962
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
2963
#endif
2964
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
2965
            return;
2966
        }
2967
    }
2968
    if (msr_ee != 0) {
2969
        /* Watchdog timer on embedded PowerPC */
2970
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
2971
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
2972
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
2973
            return;
2974
        }
2975
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
2976
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
2977
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
2978
            return;
2979
        }
2980
        /* Fixed interval timer on embedded PowerPC */
2981
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
2982
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
2983
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
2984
            return;
2985
        }
2986
        /* Programmable interval timer on embedded PowerPC */
2987
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
2988
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
2989
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
2990
            return;
2991
        }
2992
        /* Decrementer exception */
2993
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
2994
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
2995
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
2996
            return;
2997
        }
2998
        /* External interrupt */
2999
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
3000
            /* Taking an external interrupt does not clear the external
3001
             * interrupt status
3002
             */
3003
#if 0
3004
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
3005
#endif
3006
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
3007
            return;
3008
        }
3009
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
3010
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
3011
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
3012
            return;
3013
        }
3014
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
3015
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
3016
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
3017
            return;
3018
        }
3019
        /* Thermal interrupt */
3020
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
3021
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
3022
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
3023
            return;
3024
        }
3025
    }
3026
}
3027
#endif /* !CONFIG_USER_ONLY */
3028

    
3029
void cpu_dump_rfi (target_ulong RA, target_ulong msr)
3030
{
3031
    qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
3032
             TARGET_FMT_lx "\n", RA, msr);
3033
}
3034

    
3035
void cpu_reset(CPUPPCState *env)
3036
{
3037
    target_ulong msr;
3038

    
3039
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
3040
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
3041
        log_cpu_state(env, 0);
3042
    }
3043

    
3044
    msr = (target_ulong)0;
3045
    if (0) {
3046
        /* XXX: find a suitable condition to enable the hypervisor mode */
3047
        msr |= (target_ulong)MSR_HVB;
3048
    }
3049
    msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
3050
    msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
3051
    msr |= (target_ulong)1 << MSR_EP;
3052
#if defined (DO_SINGLE_STEP) && 0
3053
    /* Single step trace mode */
3054
    msr |= (target_ulong)1 << MSR_SE;
3055
    msr |= (target_ulong)1 << MSR_BE;
3056
#endif
3057
#if defined(CONFIG_USER_ONLY)
3058
    msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
3059
    msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
3060
    msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
3061
    msr |= (target_ulong)1 << MSR_PR;
3062
#else
3063
    env->excp_prefix = env->hreset_excp_prefix;
3064
    env->nip = env->hreset_vector | env->excp_prefix;
3065
    if (env->mmu_model != POWERPC_MMU_REAL)
3066
        ppc_tlb_invalidate_all(env);
3067
#endif
3068
    env->msr = msr & env->msr_mask;
3069
#if defined(TARGET_PPC64)
3070
    if (env->mmu_model & POWERPC_MMU_64)
3071
        env->msr |= (1ULL << MSR_SF);
3072
#endif
3073
    hreg_compute_hflags(env);
3074
    env->reserve_addr = (target_ulong)-1ULL;
3075
    /* Be sure no exception or interrupt is pending */
3076
    env->pending_interrupts = 0;
3077
    env->exception_index = POWERPC_EXCP_NONE;
3078
    env->error_code = 0;
3079
    /* Flush all TLBs */
3080
    tlb_flush(env, 1);
3081
}
3082

    
3083
CPUPPCState *cpu_ppc_init (const char *cpu_model)
3084
{
3085
    CPUPPCState *env;
3086
    const ppc_def_t *def;
3087

    
3088
    def = cpu_ppc_find_by_name(cpu_model);
3089
    if (!def)
3090
        return NULL;
3091

    
3092
    env = g_malloc0(sizeof(CPUPPCState));
3093
    cpu_exec_init(env);
3094
    if (tcg_enabled()) {
3095
        ppc_translate_init();
3096
    }
3097
    env->cpu_model_str = cpu_model;
3098
    cpu_ppc_register_internal(env, def);
3099

    
3100
    qemu_init_vcpu(env);
3101

    
3102
    return env;
3103
}
3104

    
3105
void cpu_ppc_close (CPUPPCState *env)
3106
{
3107
    /* Should also remove all opcode tables... */
3108
    g_free(env);
3109
}