Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ d12d51d5

History | View | Annotate | Download (93 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, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19
 */
20
#include <stdarg.h>
21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <string.h>
24
#include <inttypes.h>
25
#include <signal.h>
26
#include <assert.h>
27

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

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

    
42
#ifdef DEBUG_MMU
43
#  define LOG_MMU(...) do {              \
44
     if (loglevel)                       \
45
       fprintf(logfile, ## __VA_ARGS__); \
46
   } while (0)
47
#  define LOG_MMU_STATE(env) do {                     \
48
        if (loglevel)                                 \
49
            cpu_dump_state(env, logfile, fprintf, 0); \
50
   } while (0)
51
#else
52
#  define LOG_MMU(...) do { } while (0)
53
#  define LOG_MMU_STATE(...) do { } while (0)
54
#endif
55

    
56

    
57
#ifdef DEBUG_SOFTWARE_TLB
58
#  define LOG_SWTLB(...) do {            \
59
     if (loglevel)                       \
60
       fprintf(logfile, ## __VA_ARGS__); \
61
   } while (0)
62
#else
63
#  define LOG_SWTLB(...) do { } while (0)
64
#endif
65

    
66
#ifdef DEBUG_BATS
67
#  define LOG_BATS(...) do {             \
68
     if (loglevel)                       \
69
       fprintf(logfile, ## __VA_ARGS__); \
70
   } while (0)
71
#else
72
#  define LOG_BATS(...) do { } while (0)
73
#endif
74

    
75
#ifdef DEBUG_SLB
76
#  define LOG_SLB(...) do {              \
77
     if (loglevel)                       \
78
       fprintf(logfile, ## __VA_ARGS__); \
79
   } while (0)
80
#else
81
#  define LOG_SLB(...) do { } while (0)
82
#endif
83

    
84
#ifdef DEBUG_EXCEPTIONS
85
#  define LOG_EXCP(...) do {             \
86
     if (loglevel)                       \
87
       fprintf(logfile, ## __VA_ARGS__); \
88
   } while (0)
89
#else
90
#  define LOG_EXCP(...) do { } while (0)
91
#endif
92

    
93

    
94
/*****************************************************************************/
95
/* PowerPC MMU emulation */
96

    
97
#if defined(CONFIG_USER_ONLY)
98
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
99
                              int mmu_idx, int is_softmmu)
100
{
101
    int exception, error_code;
102

    
103
    if (rw == 2) {
104
        exception = POWERPC_EXCP_ISI;
105
        error_code = 0x40000000;
106
    } else {
107
        exception = POWERPC_EXCP_DSI;
108
        error_code = 0x40000000;
109
        if (rw)
110
            error_code |= 0x02000000;
111
        env->spr[SPR_DAR] = address;
112
        env->spr[SPR_DSISR] = error_code;
113
    }
114
    env->exception_index = exception;
115
    env->error_code = error_code;
116

    
117
    return 1;
118
}
119

    
120
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
121
{
122
    return addr;
123
}
124

    
125
#else
126
/* Common routines used by software and hardware TLBs emulation */
127
static always_inline int pte_is_valid (target_ulong pte0)
128
{
129
    return pte0 & 0x80000000 ? 1 : 0;
130
}
131

    
132
static always_inline void pte_invalidate (target_ulong *pte0)
133
{
134
    *pte0 &= ~0x80000000;
135
}
136

    
137
#if defined(TARGET_PPC64)
138
static always_inline int pte64_is_valid (target_ulong pte0)
139
{
140
    return pte0 & 0x0000000000000001ULL ? 1 : 0;
141
}
142

    
143
static always_inline void pte64_invalidate (target_ulong *pte0)
144
{
145
    *pte0 &= ~0x0000000000000001ULL;
146
}
147
#endif
148

    
149
#define PTE_PTEM_MASK 0x7FFFFFBF
150
#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
151
#if defined(TARGET_PPC64)
152
#define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
153
#define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
154
#endif
155

    
156
static always_inline int pp_check (int key, int pp, int nx)
157
{
158
    int access;
159

    
160
    /* Compute access rights */
161
    /* When pp is 3/7, the result is undefined. Set it to noaccess */
162
    access = 0;
163
    if (key == 0) {
164
        switch (pp) {
165
        case 0x0:
166
        case 0x1:
167
        case 0x2:
168
            access |= PAGE_WRITE;
169
            /* No break here */
170
        case 0x3:
171
        case 0x6:
172
            access |= PAGE_READ;
173
            break;
174
        }
175
    } else {
176
        switch (pp) {
177
        case 0x0:
178
        case 0x6:
179
            access = 0;
180
            break;
181
        case 0x1:
182
        case 0x3:
183
            access = PAGE_READ;
184
            break;
185
        case 0x2:
186
            access = PAGE_READ | PAGE_WRITE;
187
            break;
188
        }
189
    }
190
    if (nx == 0)
191
        access |= PAGE_EXEC;
192

    
193
    return access;
194
}
195

    
196
static always_inline int check_prot (int prot, int rw, int access_type)
197
{
198
    int ret;
199

    
200
    if (access_type == ACCESS_CODE) {
201
        if (prot & PAGE_EXEC)
202
            ret = 0;
203
        else
204
            ret = -2;
205
    } else if (rw) {
206
        if (prot & PAGE_WRITE)
207
            ret = 0;
208
        else
209
            ret = -2;
210
    } else {
211
        if (prot & PAGE_READ)
212
            ret = 0;
213
        else
214
            ret = -2;
215
    }
216

    
217
    return ret;
218
}
219

    
220
static always_inline int _pte_check (mmu_ctx_t *ctx, int is_64b,
221
                                     target_ulong pte0, target_ulong pte1,
222
                                     int h, int rw, int type)
223
{
224
    target_ulong ptem, mmask;
225
    int access, ret, pteh, ptev, pp;
226

    
227
    access = 0;
228
    ret = -1;
229
    /* Check validity and table match */
230
#if defined(TARGET_PPC64)
231
    if (is_64b) {
232
        ptev = pte64_is_valid(pte0);
233
        pteh = (pte0 >> 1) & 1;
234
    } else
235
#endif
236
    {
237
        ptev = pte_is_valid(pte0);
238
        pteh = (pte0 >> 6) & 1;
239
    }
240
    if (ptev && h == pteh) {
241
        /* Check vsid & api */
242
#if defined(TARGET_PPC64)
243
        if (is_64b) {
244
            ptem = pte0 & PTE64_PTEM_MASK;
245
            mmask = PTE64_CHECK_MASK;
246
            pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
247
            ctx->nx |= (pte1 >> 2) & 1; /* No execute bit */
248
            ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
249
        } else
250
#endif
251
        {
252
            ptem = pte0 & PTE_PTEM_MASK;
253
            mmask = PTE_CHECK_MASK;
254
            pp = pte1 & 0x00000003;
255
        }
256
        if (ptem == ctx->ptem) {
257
            if (ctx->raddr != (target_phys_addr_t)-1ULL) {
258
                /* all matches should have equal RPN, WIMG & PP */
259
                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
260
                    if (loglevel != 0)
261
                        fprintf(logfile, "Bad RPN/WIMG/PP\n");
262
                    return -3;
263
                }
264
            }
265
            /* Compute access rights */
266
            access = pp_check(ctx->key, pp, ctx->nx);
267
            /* Keep the matching PTE informations */
268
            ctx->raddr = pte1;
269
            ctx->prot = access;
270
            ret = check_prot(ctx->prot, rw, type);
271
            if (ret == 0) {
272
                /* Access granted */
273
                LOG_MMU("PTE access granted !\n");
274
            } else {
275
                /* Access right violation */
276
                LOG_MMU("PTE access rejected\n");
277
            }
278
        }
279
    }
280

    
281
    return ret;
282
}
283

    
284
static always_inline int pte32_check (mmu_ctx_t *ctx,
285
                                      target_ulong pte0, target_ulong pte1,
286
                                      int h, int rw, int type)
287
{
288
    return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
289
}
290

    
291
#if defined(TARGET_PPC64)
292
static always_inline int pte64_check (mmu_ctx_t *ctx,
293
                                      target_ulong pte0, target_ulong pte1,
294
                                      int h, int rw, int type)
295
{
296
    return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
297
}
298
#endif
299

    
300
static always_inline int pte_update_flags (mmu_ctx_t *ctx, target_ulong *pte1p,
301
                                           int ret, int rw)
302
{
303
    int store = 0;
304

    
305
    /* Update page flags */
306
    if (!(*pte1p & 0x00000100)) {
307
        /* Update accessed flag */
308
        *pte1p |= 0x00000100;
309
        store = 1;
310
    }
311
    if (!(*pte1p & 0x00000080)) {
312
        if (rw == 1 && ret == 0) {
313
            /* Update changed flag */
314
            *pte1p |= 0x00000080;
315
            store = 1;
316
        } else {
317
            /* Force page fault for first write access */
318
            ctx->prot &= ~PAGE_WRITE;
319
        }
320
    }
321

    
322
    return store;
323
}
324

    
325
/* Software driven TLB helpers */
326
static always_inline int ppc6xx_tlb_getnum (CPUState *env, target_ulong eaddr,
327
                                            int way, int is_code)
328
{
329
    int nr;
330

    
331
    /* Select TLB num in a way from address */
332
    nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
333
    /* Select TLB way */
334
    nr += env->tlb_per_way * way;
335
    /* 6xx have separate TLBs for instructions and data */
336
    if (is_code && env->id_tlbs == 1)
337
        nr += env->nb_tlb;
338

    
339
    return nr;
340
}
341

    
342
static always_inline void ppc6xx_tlb_invalidate_all (CPUState *env)
343
{
344
    ppc6xx_tlb_t *tlb;
345
    int nr, max;
346

    
347
    //LOG_SWTLB("Invalidate all TLBs\n");
348
    /* Invalidate all defined software TLB */
349
    max = env->nb_tlb;
350
    if (env->id_tlbs == 1)
351
        max *= 2;
352
    for (nr = 0; nr < max; nr++) {
353
        tlb = &env->tlb[nr].tlb6;
354
        pte_invalidate(&tlb->pte0);
355
    }
356
    tlb_flush(env, 1);
357
}
358

    
359
static always_inline void __ppc6xx_tlb_invalidate_virt (CPUState *env,
360
                                                        target_ulong eaddr,
361
                                                        int is_code,
362
                                                        int match_epn)
363
{
364
#if !defined(FLUSH_ALL_TLBS)
365
    ppc6xx_tlb_t *tlb;
366
    int way, nr;
367

    
368
    /* Invalidate ITLB + DTLB, all ways */
369
    for (way = 0; way < env->nb_ways; way++) {
370
        nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
371
        tlb = &env->tlb[nr].tlb6;
372
        if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
373
            LOG_SWTLB("TLB invalidate %d/%d " ADDRX "\n",
374
                        nr, env->nb_tlb, eaddr);
375
            pte_invalidate(&tlb->pte0);
376
            tlb_flush_page(env, tlb->EPN);
377
        }
378
    }
379
#else
380
    /* XXX: PowerPC specification say this is valid as well */
381
    ppc6xx_tlb_invalidate_all(env);
382
#endif
383
}
384

    
385
static always_inline void ppc6xx_tlb_invalidate_virt (CPUState *env,
386
                                                      target_ulong eaddr,
387
                                                      int is_code)
388
{
389
    __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
390
}
391

    
392
void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
393
                       target_ulong pte0, target_ulong pte1)
394
{
395
    ppc6xx_tlb_t *tlb;
396
    int nr;
397

    
398
    nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
399
    tlb = &env->tlb[nr].tlb6;
400
    LOG_SWTLB("Set TLB %d/%d EPN " ADDRX " PTE0 " ADDRX
401
                " PTE1 " ADDRX "\n", nr, env->nb_tlb, EPN, pte0, pte1);
402
    /* Invalidate any pending reference in Qemu for this virtual address */
403
    __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
404
    tlb->pte0 = pte0;
405
    tlb->pte1 = pte1;
406
    tlb->EPN = EPN;
407
    /* Store last way for LRU mechanism */
408
    env->last_way = way;
409
}
410

    
411
static always_inline int ppc6xx_tlb_check (CPUState *env, mmu_ctx_t *ctx,
412
                                           target_ulong eaddr, int rw,
413
                                           int access_type)
414
{
415
    ppc6xx_tlb_t *tlb;
416
    int nr, best, way;
417
    int ret;
418

    
419
    best = -1;
420
    ret = -1; /* No TLB found */
421
    for (way = 0; way < env->nb_ways; way++) {
422
        nr = ppc6xx_tlb_getnum(env, eaddr, way,
423
                               access_type == ACCESS_CODE ? 1 : 0);
424
        tlb = &env->tlb[nr].tlb6;
425
        /* This test "emulates" the PTE index match for hardware TLBs */
426
        if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
427
            LOG_SWTLB("TLB %d/%d %s [" ADDRX " " ADDRX
428
                        "] <> " ADDRX "\n",
429
                        nr, env->nb_tlb,
430
                        pte_is_valid(tlb->pte0) ? "valid" : "inval",
431
                        tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
432
            continue;
433
        }
434
        LOG_SWTLB("TLB %d/%d %s " ADDRX " <> " ADDRX " " ADDRX
435
                    " %c %c\n",
436
                    nr, env->nb_tlb,
437
                    pte_is_valid(tlb->pte0) ? "valid" : "inval",
438
                    tlb->EPN, eaddr, tlb->pte1,
439
                    rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
440
        switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
441
        case -3:
442
            /* TLB inconsistency */
443
            return -1;
444
        case -2:
445
            /* Access violation */
446
            ret = -2;
447
            best = nr;
448
            break;
449
        case -1:
450
        default:
451
            /* No match */
452
            break;
453
        case 0:
454
            /* access granted */
455
            /* XXX: we should go on looping to check all TLBs consistency
456
             *      but we can speed-up the whole thing as the
457
             *      result would be undefined if TLBs are not consistent.
458
             */
459
            ret = 0;
460
            best = nr;
461
            goto done;
462
        }
463
    }
464
    if (best != -1) {
465
    done:
466
        LOG_SWTLB("found TLB at addr " PADDRX " prot=%01x ret=%d\n",
467
                    ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
468
        /* Update page flags */
469
        pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
470
    }
471

    
472
    return ret;
473
}
474

    
475
/* Perform BAT hit & translation */
476
static always_inline void bat_size_prot (CPUState *env, target_ulong *blp,
477
                                         int *validp, int *protp,
478
                                         target_ulong *BATu, target_ulong *BATl)
479
{
480
    target_ulong bl;
481
    int pp, valid, prot;
482

    
483
    bl = (*BATu & 0x00001FFC) << 15;
484
    valid = 0;
485
    prot = 0;
486
    if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
487
        ((msr_pr != 0) && (*BATu & 0x00000001))) {
488
        valid = 1;
489
        pp = *BATl & 0x00000003;
490
        if (pp != 0) {
491
            prot = PAGE_READ | PAGE_EXEC;
492
            if (pp == 0x2)
493
                prot |= PAGE_WRITE;
494
        }
495
    }
496
    *blp = bl;
497
    *validp = valid;
498
    *protp = prot;
499
}
500

    
501
static always_inline void bat_601_size_prot (CPUState *env,target_ulong *blp,
502
                                             int *validp, int *protp,
503
                                             target_ulong *BATu,
504
                                             target_ulong *BATl)
505
{
506
    target_ulong bl;
507
    int key, pp, valid, prot;
508

    
509
    bl = (*BATl & 0x0000003F) << 17;
510
    LOG_BATS("b %02x ==> bl " ADDRX " msk " ADDRX "\n",
511
                (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
512
    prot = 0;
513
    valid = (*BATl >> 6) & 1;
514
    if (valid) {
515
        pp = *BATu & 0x00000003;
516
        if (msr_pr == 0)
517
            key = (*BATu >> 3) & 1;
518
        else
519
            key = (*BATu >> 2) & 1;
520
        prot = pp_check(key, pp, 0);
521
    }
522
    *blp = bl;
523
    *validp = valid;
524
    *protp = prot;
525
}
526

    
527
static always_inline int get_bat (CPUState *env, mmu_ctx_t *ctx,
528
                                  target_ulong virtual, int rw, int type)
529
{
530
    target_ulong *BATlt, *BATut, *BATu, *BATl;
531
    target_ulong base, BEPIl, BEPIu, bl;
532
    int i, valid, prot;
533
    int ret = -1;
534

    
535
    LOG_BATS("%s: %cBAT v " ADDRX "\n", __func__,
536
                type == ACCESS_CODE ? 'I' : 'D', virtual);
537
    switch (type) {
538
    case ACCESS_CODE:
539
        BATlt = env->IBAT[1];
540
        BATut = env->IBAT[0];
541
        break;
542
    default:
543
        BATlt = env->DBAT[1];
544
        BATut = env->DBAT[0];
545
        break;
546
    }
547
    base = virtual & 0xFFFC0000;
548
    for (i = 0; i < env->nb_BATs; i++) {
549
        BATu = &BATut[i];
550
        BATl = &BATlt[i];
551
        BEPIu = *BATu & 0xF0000000;
552
        BEPIl = *BATu & 0x0FFE0000;
553
        if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
554
            bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
555
        } else {
556
            bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
557
        }
558
        LOG_BATS("%s: %cBAT%d v " ADDRX " BATu " ADDRX
559
                    " BATl " ADDRX "\n", __func__,
560
                    type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
561
        if ((virtual & 0xF0000000) == BEPIu &&
562
            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
563
            /* BAT matches */
564
            if (valid != 0) {
565
                /* Get physical address */
566
                ctx->raddr = (*BATl & 0xF0000000) |
567
                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
568
                    (virtual & 0x0001F000);
569
                /* Compute access rights */
570
                ctx->prot = prot;
571
                ret = check_prot(ctx->prot, rw, type);
572
                if (ret == 0)
573
                    LOG_BATS("BAT %d match: r " PADDRX " prot=%c%c\n",
574
                             i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
575
                             ctx->prot & PAGE_WRITE ? 'W' : '-');
576
                break;
577
            }
578
        }
579
    }
580
    if (ret < 0) {
581
#if defined(DEBUG_BATS)
582
        if (IS_LOGGING) {
583
            QEMU_LOG0("no BAT match for " ADDRX ":\n", virtual);
584
            for (i = 0; i < 4; i++) {
585
                BATu = &BATut[i];
586
                BATl = &BATlt[i];
587
                BEPIu = *BATu & 0xF0000000;
588
                BEPIl = *BATu & 0x0FFE0000;
589
                bl = (*BATu & 0x00001FFC) << 15;
590
                QEMU_LOG0("%s: %cBAT%d v " ADDRX " BATu " ADDRX
591
                        " BATl " ADDRX " \n\t" ADDRX " " ADDRX " " ADDRX "\n",
592
                        __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
593
                        *BATu, *BATl, BEPIu, BEPIl, bl);
594
            }
595
        }
596
#endif
597
    }
598
    /* No hit */
599
    return ret;
600
}
601

    
602
/* PTE table lookup */
603
static always_inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h,
604
                                    int rw, int type)
605
{
606
    target_ulong base, pte0, pte1;
607
    int i, good = -1;
608
    int ret, r;
609

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

    
677
    return ret;
678
}
679

    
680
static always_inline int find_pte32 (mmu_ctx_t *ctx, int h, int rw, int type)
681
{
682
    return _find_pte(ctx, 0, h, rw, type);
683
}
684

    
685
#if defined(TARGET_PPC64)
686
static always_inline int find_pte64 (mmu_ctx_t *ctx, int h, int rw, int type)
687
{
688
    return _find_pte(ctx, 1, h, rw, type);
689
}
690
#endif
691

    
692
static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx,
693
                                   int h, int rw, int type)
694
{
695
#if defined(TARGET_PPC64)
696
    if (env->mmu_model & POWERPC_MMU_64)
697
        return find_pte64(ctx, h, rw, type);
698
#endif
699

    
700
    return find_pte32(ctx, h, rw, type);
701
}
702

    
703
#if defined(TARGET_PPC64)
704
static always_inline int slb_is_valid (uint64_t slb64)
705
{
706
    return slb64 & 0x0000000008000000ULL ? 1 : 0;
707
}
708

    
709
static always_inline void slb_invalidate (uint64_t *slb64)
710
{
711
    *slb64 &= ~0x0000000008000000ULL;
712
}
713

    
714
static always_inline int slb_lookup (CPUPPCState *env, target_ulong eaddr,
715
                                     target_ulong *vsid,
716
                                     target_ulong *page_mask, int *attr)
717
{
718
    target_phys_addr_t sr_base;
719
    target_ulong mask;
720
    uint64_t tmp64;
721
    uint32_t tmp;
722
    int n, ret;
723

    
724
    ret = -5;
725
    sr_base = env->spr[SPR_ASR];
726
    LOG_SLB("%s: eaddr " ADDRX " base " PADDRX "\n",
727
                __func__, eaddr, sr_base);
728
    mask = 0x0000000000000000ULL; /* Avoid gcc warning */
729
    for (n = 0; n < env->slb_nr; n++) {
730
        tmp64 = ldq_phys(sr_base);
731
        tmp = ldl_phys(sr_base + 8);
732
        LOG_SLB("%s: seg %d " PADDRX " %016" PRIx64 " %08"
733
                    PRIx32 "\n", __func__, n, sr_base, tmp64, tmp);
734
        if (slb_is_valid(tmp64)) {
735
            /* SLB entry is valid */
736
            switch (tmp64 & 0x0000000006000000ULL) {
737
            case 0x0000000000000000ULL:
738
                /* 256 MB segment */
739
                mask = 0xFFFFFFFFF0000000ULL;
740
                break;
741
            case 0x0000000002000000ULL:
742
                /* 1 TB segment */
743
                mask = 0xFFFF000000000000ULL;
744
                break;
745
            case 0x0000000004000000ULL:
746
            case 0x0000000006000000ULL:
747
                /* Reserved => segment is invalid */
748
                continue;
749
            }
750
            if ((eaddr & mask) == (tmp64 & mask)) {
751
                /* SLB match */
752
                *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
753
                *page_mask = ~mask;
754
                *attr = tmp & 0xFF;
755
                ret = n;
756
                break;
757
            }
758
        }
759
        sr_base += 12;
760
    }
761

    
762
    return ret;
763
}
764

    
765
void ppc_slb_invalidate_all (CPUPPCState *env)
766
{
767
    target_phys_addr_t sr_base;
768
    uint64_t tmp64;
769
    int n, do_invalidate;
770

    
771
    do_invalidate = 0;
772
    sr_base = env->spr[SPR_ASR];
773
    /* XXX: Warning: slbia never invalidates the first segment */
774
    for (n = 1; n < env->slb_nr; n++) {
775
        tmp64 = ldq_phys(sr_base);
776
        if (slb_is_valid(tmp64)) {
777
            slb_invalidate(&tmp64);
778
            stq_phys(sr_base, tmp64);
779
            /* XXX: given the fact that segment size is 256 MB or 1TB,
780
             *      and we still don't have a tlb_flush_mask(env, n, mask)
781
             *      in Qemu, we just invalidate all TLBs
782
             */
783
            do_invalidate = 1;
784
        }
785
        sr_base += 12;
786
    }
787
    if (do_invalidate)
788
        tlb_flush(env, 1);
789
}
790

    
791
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
792
{
793
    target_phys_addr_t sr_base;
794
    target_ulong vsid, page_mask;
795
    uint64_t tmp64;
796
    int attr;
797
    int n;
798

    
799
    n = slb_lookup(env, T0, &vsid, &page_mask, &attr);
800
    if (n >= 0) {
801
        sr_base = env->spr[SPR_ASR];
802
        sr_base += 12 * n;
803
        tmp64 = ldq_phys(sr_base);
804
        if (slb_is_valid(tmp64)) {
805
            slb_invalidate(&tmp64);
806
            stq_phys(sr_base, tmp64);
807
            /* XXX: given the fact that segment size is 256 MB or 1TB,
808
             *      and we still don't have a tlb_flush_mask(env, n, mask)
809
             *      in Qemu, we just invalidate all TLBs
810
             */
811
            tlb_flush(env, 1);
812
        }
813
    }
814
}
815

    
816
target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
817
{
818
    target_phys_addr_t sr_base;
819
    target_ulong rt;
820
    uint64_t tmp64;
821
    uint32_t tmp;
822

    
823
    sr_base = env->spr[SPR_ASR];
824
    sr_base += 12 * slb_nr;
825
    tmp64 = ldq_phys(sr_base);
826
    tmp = ldl_phys(sr_base + 8);
827
    if (tmp64 & 0x0000000008000000ULL) {
828
        /* SLB entry is valid */
829
        /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
830
        rt = tmp >> 8;             /* 65:88 => 40:63 */
831
        rt |= (tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
832
        /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
833
        rt |= ((tmp >> 4) & 0xF) << 27;
834
    } else {
835
        rt = 0;
836
    }
837
    LOG_SLB("%s: " PADDRX " %016" PRIx64 " %08" PRIx32 " => %d "
838
                ADDRX "\n", __func__, sr_base, tmp64, tmp, slb_nr, rt);
839

    
840
    return rt;
841
}
842

    
843
void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs)
844
{
845
    target_phys_addr_t sr_base;
846
    uint64_t tmp64;
847
    uint32_t tmp;
848

    
849
    sr_base = env->spr[SPR_ASR];
850
    sr_base += 12 * slb_nr;
851
    /* Copy Rs bits 37:63 to SLB 62:88 */
852
    tmp = rs << 8;
853
    tmp64 = (rs >> 24) & 0x7;
854
    /* Copy Rs bits 33:36 to SLB 89:92 */
855
    tmp |= ((rs >> 27) & 0xF) << 4;
856
    /* Set the valid bit */
857
    tmp64 |= 1 << 27;
858
    /* Set ESID */
859
    tmp64 |= (uint32_t)slb_nr << 28;
860
    LOG_SLB("%s: %d " ADDRX " => " PADDRX " %016" PRIx64
861
                " %08" PRIx32 "\n", __func__,
862
                slb_nr, rs, sr_base, tmp64, tmp);
863
    /* Write SLB entry to memory */
864
    stq_phys(sr_base, tmp64);
865
    stl_phys(sr_base + 8, tmp);
866
}
867
#endif /* defined(TARGET_PPC64) */
868

    
869
/* Perform segment based translation */
870
static always_inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
871
                                                    int sdr_sh,
872
                                                    target_phys_addr_t hash,
873
                                                    target_phys_addr_t mask)
874
{
875
    return (sdr1 & ((target_phys_addr_t)(-1ULL) << sdr_sh)) | (hash & mask);
876
}
877

    
878
static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
879
                                      target_ulong eaddr, int rw, int type)
880
{
881
    target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
882
    target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
883
#if defined(TARGET_PPC64)
884
    int attr;
885
#endif
886
    int ds, vsid_sh, sdr_sh, pr;
887
    int ret, ret2;
888

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

    
1054
    return ret;
1055
}
1056

    
1057
/* Generic TLB check function for embedded PowerPC implementations */
1058
static always_inline int ppcemb_tlb_check (CPUState *env, ppcemb_tlb_t *tlb,
1059
                                           target_phys_addr_t *raddrp,
1060
                                           target_ulong address,
1061
                                           uint32_t pid, int ext, int i)
1062
{
1063
    target_ulong mask;
1064

    
1065
    /* Check valid flag */
1066
    if (!(tlb->prot & PAGE_VALID)) {
1067
        if (loglevel != 0)
1068
            fprintf(logfile, "%s: TLB %d not valid\n", __func__, i);
1069
        return -1;
1070
    }
1071
    mask = ~(tlb->size - 1);
1072
    LOG_SWTLB("%s: TLB %d address " ADDRX " PID %u <=> " ADDRX
1073
                " " ADDRX " %u\n",
1074
                __func__, i, address, pid, tlb->EPN, mask, (uint32_t)tlb->PID);
1075
    /* Check PID */
1076
    if (tlb->PID != 0 && tlb->PID != pid)
1077
        return -1;
1078
    /* Check effective address */
1079
    if ((address & mask) != tlb->EPN)
1080
        return -1;
1081
    *raddrp = (tlb->RPN & mask) | (address & ~mask);
1082
#if (TARGET_PHYS_ADDR_BITS >= 36)
1083
    if (ext) {
1084
        /* Extend the physical address to 36 bits */
1085
        *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1086
    }
1087
#endif
1088

    
1089
    return 0;
1090
}
1091

    
1092
/* Generic TLB search function for PowerPC embedded implementations */
1093
int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1094
{
1095
    ppcemb_tlb_t *tlb;
1096
    target_phys_addr_t raddr;
1097
    int i, ret;
1098

    
1099
    /* Default return value is no match */
1100
    ret = -1;
1101
    for (i = 0; i < env->nb_tlb; i++) {
1102
        tlb = &env->tlb[i].tlbe;
1103
        if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1104
            ret = i;
1105
            break;
1106
        }
1107
    }
1108

    
1109
    return ret;
1110
}
1111

    
1112
/* Helpers specific to PowerPC 40x implementations */
1113
static always_inline void ppc4xx_tlb_invalidate_all (CPUState *env)
1114
{
1115
    ppcemb_tlb_t *tlb;
1116
    int i;
1117

    
1118
    for (i = 0; i < env->nb_tlb; i++) {
1119
        tlb = &env->tlb[i].tlbe;
1120
        tlb->prot &= ~PAGE_VALID;
1121
    }
1122
    tlb_flush(env, 1);
1123
}
1124

    
1125
static always_inline void ppc4xx_tlb_invalidate_virt (CPUState *env,
1126
                                                      target_ulong eaddr,
1127
                                                      uint32_t pid)
1128
{
1129
#if !defined(FLUSH_ALL_TLBS)
1130
    ppcemb_tlb_t *tlb;
1131
    target_phys_addr_t raddr;
1132
    target_ulong page, end;
1133
    int i;
1134

    
1135
    for (i = 0; i < env->nb_tlb; i++) {
1136
        tlb = &env->tlb[i].tlbe;
1137
        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1138
            end = tlb->EPN + tlb->size;
1139
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1140
                tlb_flush_page(env, page);
1141
            tlb->prot &= ~PAGE_VALID;
1142
            break;
1143
        }
1144
    }
1145
#else
1146
    ppc4xx_tlb_invalidate_all(env);
1147
#endif
1148
}
1149

    
1150
static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1151
                                 target_ulong address, int rw, int access_type)
1152
{
1153
    ppcemb_tlb_t *tlb;
1154
    target_phys_addr_t raddr;
1155
    int i, ret, zsel, zpr, pr;
1156

    
1157
    ret = -1;
1158
    raddr = (target_phys_addr_t)-1ULL;
1159
    pr = msr_pr;
1160
    for (i = 0; i < env->nb_tlb; i++) {
1161
        tlb = &env->tlb[i].tlbe;
1162
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1163
                             env->spr[SPR_40x_PID], 0, i) < 0)
1164
            continue;
1165
        zsel = (tlb->attr >> 4) & 0xF;
1166
        zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
1167
        LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1168
                    __func__, i, zsel, zpr, rw, tlb->attr);
1169
        /* Check execute enable bit */
1170
        switch (zpr) {
1171
        case 0x2:
1172
            if (pr != 0)
1173
                goto check_perms;
1174
            /* No break here */
1175
        case 0x3:
1176
            /* All accesses granted */
1177
            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1178
            ret = 0;
1179
            break;
1180
        case 0x0:
1181
            if (pr != 0) {
1182
                ctx->prot = 0;
1183
                ret = -2;
1184
                break;
1185
            }
1186
            /* No break here */
1187
        case 0x1:
1188
        check_perms:
1189
            /* Check from TLB entry */
1190
            /* XXX: there is a problem here or in the TLB fill code... */
1191
            ctx->prot = tlb->prot;
1192
            ctx->prot |= PAGE_EXEC;
1193
            ret = check_prot(ctx->prot, rw, access_type);
1194
            break;
1195
        }
1196
        if (ret >= 0) {
1197
            ctx->raddr = raddr;
1198
            LOG_SWTLB("%s: access granted " ADDRX " => " PADDRX
1199
                        " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1200
                        ret);
1201
            return 0;
1202
        }
1203
    }
1204
    LOG_SWTLB("%s: access refused " ADDRX " => " PADDRX
1205
                " %d %d\n", __func__, address, raddr, ctx->prot,
1206
                ret);
1207

    
1208
    return ret;
1209
}
1210

    
1211
void store_40x_sler (CPUPPCState *env, uint32_t val)
1212
{
1213
    /* XXX: TO BE FIXED */
1214
    if (val != 0x00000000) {
1215
        cpu_abort(env, "Little-endian regions are not supported by now\n");
1216
    }
1217
    env->spr[SPR_405_SLER] = val;
1218
}
1219

    
1220
static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1221
                                          target_ulong address, int rw,
1222
                                          int access_type)
1223
{
1224
    ppcemb_tlb_t *tlb;
1225
    target_phys_addr_t raddr;
1226
    int i, prot, ret;
1227

    
1228
    ret = -1;
1229
    raddr = (target_phys_addr_t)-1ULL;
1230
    for (i = 0; i < env->nb_tlb; i++) {
1231
        tlb = &env->tlb[i].tlbe;
1232
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1233
                             env->spr[SPR_BOOKE_PID], 1, i) < 0)
1234
            continue;
1235
        if (msr_pr != 0)
1236
            prot = tlb->prot & 0xF;
1237
        else
1238
            prot = (tlb->prot >> 4) & 0xF;
1239
        /* Check the address space */
1240
        if (access_type == ACCESS_CODE) {
1241
            if (msr_ir != (tlb->attr & 1))
1242
                continue;
1243
            ctx->prot = prot;
1244
            if (prot & PAGE_EXEC) {
1245
                ret = 0;
1246
                break;
1247
            }
1248
            ret = -3;
1249
        } else {
1250
            if (msr_dr != (tlb->attr & 1))
1251
                continue;
1252
            ctx->prot = prot;
1253
            if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
1254
                ret = 0;
1255
                break;
1256
            }
1257
            ret = -2;
1258
        }
1259
    }
1260
    if (ret >= 0)
1261
        ctx->raddr = raddr;
1262

    
1263
    return ret;
1264
}
1265

    
1266
static always_inline int check_physical (CPUState *env, mmu_ctx_t *ctx,
1267
                                         target_ulong eaddr, int rw)
1268
{
1269
    int in_plb, ret;
1270

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

    
1329
    return ret;
1330
}
1331

    
1332
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1333
                          int rw, int access_type)
1334
{
1335
    int ret;
1336

    
1337
#if 0
1338
    if (loglevel != 0) {
1339
        fprintf(logfile, "%s\n", __func__);
1340
    }
1341
#endif
1342
    if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1343
        (access_type != ACCESS_CODE && msr_dr == 0)) {
1344
        /* No address translation */
1345
        ret = check_physical(env, ctx, eaddr, rw);
1346
    } else {
1347
        ret = -1;
1348
        switch (env->mmu_model) {
1349
        case POWERPC_MMU_32B:
1350
        case POWERPC_MMU_601:
1351
        case POWERPC_MMU_SOFT_6xx:
1352
        case POWERPC_MMU_SOFT_74xx:
1353
#if defined(TARGET_PPC64)
1354
        case POWERPC_MMU_620:
1355
        case POWERPC_MMU_64B:
1356
#endif
1357
            /* Try to find a BAT */
1358
            if (env->nb_BATs != 0)
1359
                ret = get_bat(env, ctx, eaddr, rw, access_type);
1360
            if (ret < 0) {
1361
                /* We didn't match any BAT entry or don't have BATs */
1362
                ret = get_segment(env, ctx, eaddr, rw, access_type);
1363
            }
1364
            break;
1365
        case POWERPC_MMU_SOFT_4xx:
1366
        case POWERPC_MMU_SOFT_4xx_Z:
1367
            ret = mmu40x_get_physical_address(env, ctx, eaddr,
1368
                                              rw, access_type);
1369
            break;
1370
        case POWERPC_MMU_BOOKE:
1371
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1372
                                                rw, access_type);
1373
            break;
1374
        case POWERPC_MMU_MPC8xx:
1375
            /* XXX: TODO */
1376
            cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1377
            break;
1378
        case POWERPC_MMU_BOOKE_FSL:
1379
            /* XXX: TODO */
1380
            cpu_abort(env, "BookE FSL MMU model not implemented\n");
1381
            return -1;
1382
        case POWERPC_MMU_REAL:
1383
            cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1384
            return -1;
1385
        default:
1386
            cpu_abort(env, "Unknown or invalid MMU model\n");
1387
            return -1;
1388
        }
1389
    }
1390
#if 0
1391
    if (loglevel != 0) {
1392
        fprintf(logfile, "%s address " ADDRX " => %d " PADDRX "\n",
1393
                __func__, eaddr, ret, ctx->raddr);
1394
    }
1395
#endif
1396

    
1397
    return ret;
1398
}
1399

    
1400
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1401
{
1402
    mmu_ctx_t ctx;
1403

    
1404
    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1405
        return -1;
1406

    
1407
    return ctx.raddr & TARGET_PAGE_MASK;
1408
}
1409

    
1410
/* Perform address translation */
1411
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1412
                              int mmu_idx, int is_softmmu)
1413
{
1414
    mmu_ctx_t ctx;
1415
    int access_type;
1416
    int ret = 0;
1417

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

    
1668
    return ret;
1669
}
1670

    
1671
/*****************************************************************************/
1672
/* BATs management */
1673
#if !defined(FLUSH_ALL_TLBS)
1674
static always_inline void do_invalidate_BAT (CPUPPCState *env,
1675
                                             target_ulong BATu,
1676
                                             target_ulong mask)
1677
{
1678
    target_ulong base, end, page;
1679

    
1680
    base = BATu & ~0x0001FFFF;
1681
    end = base + mask + 0x00020000;
1682
    LOG_BATS("Flush BAT from " ADDRX " to " ADDRX " (" ADDRX ")\n",
1683
                base, end, mask);
1684
    for (page = base; page != end; page += TARGET_PAGE_SIZE)
1685
        tlb_flush_page(env, page);
1686
    LOG_BATS("Flush done\n");
1687
}
1688
#endif
1689

    
1690
static always_inline void dump_store_bat (CPUPPCState *env, char ID,
1691
                                          int ul, int nr, target_ulong value)
1692
{
1693
    LOG_BATS("Set %cBAT%d%c to " ADDRX " (" ADDRX ")\n",
1694
                ID, nr, ul == 0 ? 'u' : 'l', value, env->nip);
1695
}
1696

    
1697
void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1698
{
1699
    target_ulong mask;
1700

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

    
1723
void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1724
{
1725
    dump_store_bat(env, 'I', 1, nr, value);
1726
    env->IBAT[1][nr] = value;
1727
}
1728

    
1729
void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1730
{
1731
    target_ulong mask;
1732

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

    
1755
void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1756
{
1757
    dump_store_bat(env, 'D', 1, nr, value);
1758
    env->DBAT[1][nr] = value;
1759
}
1760

    
1761
void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1762
{
1763
    target_ulong mask;
1764
    int do_inval;
1765

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

    
1798
void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1799
{
1800
    target_ulong mask;
1801
    int do_inval;
1802

    
1803
    dump_store_bat(env, 'I', 1, nr, value);
1804
    if (env->IBAT[1][nr] != value) {
1805
        do_inval = 0;
1806
        if (env->IBAT[1][nr] & 0x40) {
1807
#if !defined(FLUSH_ALL_TLBS)
1808
            mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1809
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1810
#else
1811
            do_inval = 1;
1812
#endif
1813
        }
1814
        if (value & 0x40) {
1815
#if !defined(FLUSH_ALL_TLBS)
1816
            mask = (value << 17) & 0x0FFE0000UL;
1817
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1818
#else
1819
            do_inval = 1;
1820
#endif
1821
        }
1822
        env->IBAT[1][nr] = value;
1823
        env->DBAT[1][nr] = value;
1824
#if defined(FLUSH_ALL_TLBS)
1825
        if (do_inval)
1826
            tlb_flush(env, 1);
1827
#endif
1828
    }
1829
}
1830

    
1831
/*****************************************************************************/
1832
/* TLB management */
1833
void ppc_tlb_invalidate_all (CPUPPCState *env)
1834
{
1835
    switch (env->mmu_model) {
1836
    case POWERPC_MMU_SOFT_6xx:
1837
    case POWERPC_MMU_SOFT_74xx:
1838
        ppc6xx_tlb_invalidate_all(env);
1839
        break;
1840
    case POWERPC_MMU_SOFT_4xx:
1841
    case POWERPC_MMU_SOFT_4xx_Z:
1842
        ppc4xx_tlb_invalidate_all(env);
1843
        break;
1844
    case POWERPC_MMU_REAL:
1845
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1846
        break;
1847
    case POWERPC_MMU_MPC8xx:
1848
        /* XXX: TODO */
1849
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1850
        break;
1851
    case POWERPC_MMU_BOOKE:
1852
        /* XXX: TODO */
1853
        cpu_abort(env, "BookE MMU model is not implemented\n");
1854
        break;
1855
    case POWERPC_MMU_BOOKE_FSL:
1856
        /* XXX: TODO */
1857
        if (!kvm_enabled())
1858
            cpu_abort(env, "BookE MMU model is not implemented\n");
1859
        break;
1860
    case POWERPC_MMU_32B:
1861
    case POWERPC_MMU_601:
1862
#if defined(TARGET_PPC64)
1863
    case POWERPC_MMU_620:
1864
    case POWERPC_MMU_64B:
1865
#endif /* defined(TARGET_PPC64) */
1866
        tlb_flush(env, 1);
1867
        break;
1868
    default:
1869
        /* XXX: TODO */
1870
        cpu_abort(env, "Unknown MMU model\n");
1871
        break;
1872
    }
1873
}
1874

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

    
1950
/*****************************************************************************/
1951
/* Special registers manipulation */
1952
#if defined(TARGET_PPC64)
1953
void ppc_store_asr (CPUPPCState *env, target_ulong value)
1954
{
1955
    if (env->asr != value) {
1956
        env->asr = value;
1957
        tlb_flush(env, 1);
1958
    }
1959
}
1960
#endif
1961

    
1962
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
1963
{
1964
    LOG_MMU("%s: " ADDRX "\n", __func__, value);
1965
    if (env->sdr1 != value) {
1966
        /* XXX: for PowerPC 64, should check that the HTABSIZE value
1967
         *      is <= 28
1968
         */
1969
        env->sdr1 = value;
1970
        tlb_flush(env, 1);
1971
    }
1972
}
1973

    
1974
void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1975
{
1976
    LOG_MMU("%s: reg=%d " ADDRX " " ADDRX "\n",
1977
                __func__, srnum, value, env->sr[srnum]);
1978
    if (env->sr[srnum] != value) {
1979
        env->sr[srnum] = value;
1980
#if !defined(FLUSH_ALL_TLBS) && 0
1981
        {
1982
            target_ulong page, end;
1983
            /* Invalidate 256 MB of virtual memory */
1984
            page = (16 << 20) * srnum;
1985
            end = page + (16 << 20);
1986
            for (; page != end; page += TARGET_PAGE_SIZE)
1987
                tlb_flush_page(env, page);
1988
        }
1989
#else
1990
        tlb_flush(env, 1);
1991
#endif
1992
    }
1993
}
1994
#endif /* !defined (CONFIG_USER_ONLY) */
1995

    
1996
/* GDBstub can read and write MSR... */
1997
void ppc_store_msr (CPUPPCState *env, target_ulong value)
1998
{
1999
    hreg_store_msr(env, value, 0);
2000
}
2001

    
2002
/*****************************************************************************/
2003
/* Exception processing */
2004
#if defined (CONFIG_USER_ONLY)
2005
void do_interrupt (CPUState *env)
2006
{
2007
    env->exception_index = POWERPC_EXCP_NONE;
2008
    env->error_code = 0;
2009
}
2010

    
2011
void ppc_hw_interrupt (CPUState *env)
2012
{
2013
    env->exception_index = POWERPC_EXCP_NONE;
2014
    env->error_code = 0;
2015
}
2016
#else /* defined (CONFIG_USER_ONLY) */
2017
static always_inline void dump_syscall (CPUState *env)
2018
{
2019
    fprintf(logfile, "syscall r0=" REGX " r3=" REGX " r4=" REGX
2020
            " r5=" REGX " r6=" REGX " nip=" ADDRX "\n",
2021
            ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4),
2022
            ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6), env->nip);
2023
}
2024

    
2025
/* Note that this function should be greatly optimized
2026
 * when called with a constant excp, from ppc_hw_interrupt
2027
 */
2028
static always_inline void powerpc_excp (CPUState *env,
2029
                                        int excp_model, int excp)
2030
{
2031
    target_ulong msr, new_msr, vector;
2032
    int srr0, srr1, asrr0, asrr1;
2033
    int lpes0, lpes1, lev;
2034

    
2035
    if (0) {
2036
        /* XXX: find a suitable condition to enable the hypervisor mode */
2037
        lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2038
        lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2039
    } else {
2040
        /* Those values ensure we won't enter the hypervisor mode */
2041
        lpes0 = 0;
2042
        lpes1 = 1;
2043
    }
2044

    
2045
    if (loglevel & CPU_LOG_INT) {
2046
        fprintf(logfile, "Raise exception at " ADDRX " => %08x (%02x)\n",
2047
                env->nip, excp, env->error_code);
2048
    }
2049
    msr = env->msr;
2050
    new_msr = msr;
2051
    srr0 = SPR_SRR0;
2052
    srr1 = SPR_SRR1;
2053
    asrr0 = -1;
2054
    asrr1 = -1;
2055
    msr &= ~((target_ulong)0x783F0000);
2056
    switch (excp) {
2057
    case POWERPC_EXCP_NONE:
2058
        /* Should never happen */
2059
        return;
2060
    case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
2061
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2062
        switch (excp_model) {
2063
        case POWERPC_EXCP_40x:
2064
            srr0 = SPR_40x_SRR2;
2065
            srr1 = SPR_40x_SRR3;
2066
            break;
2067
        case POWERPC_EXCP_BOOKE:
2068
            srr0 = SPR_BOOKE_CSRR0;
2069
            srr1 = SPR_BOOKE_CSRR1;
2070
            break;
2071
        case POWERPC_EXCP_G2:
2072
            break;
2073
        default:
2074
            goto excp_invalid;
2075
        }
2076
        goto store_next;
2077
    case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
2078
        if (msr_me == 0) {
2079
            /* Machine check exception is not enabled.
2080
             * Enter checkstop state.
2081
             */
2082
            if (loglevel != 0) {
2083
                fprintf(logfile, "Machine check while not allowed. "
2084
                        "Entering checkstop state\n");
2085
            } else {
2086
                fprintf(stderr, "Machine check while not allowed. "
2087
                        "Entering checkstop state\n");
2088
            }
2089
            env->halted = 1;
2090
            env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2091
        }
2092
        new_msr &= ~((target_ulong)1 << MSR_RI);
2093
        new_msr &= ~((target_ulong)1 << MSR_ME);
2094
        if (0) {
2095
            /* XXX: find a suitable condition to enable the hypervisor mode */
2096
            new_msr |= (target_ulong)MSR_HVB;
2097
        }
2098
        /* XXX: should also have something loaded in DAR / DSISR */
2099
        switch (excp_model) {
2100
        case POWERPC_EXCP_40x:
2101
            srr0 = SPR_40x_SRR2;
2102
            srr1 = SPR_40x_SRR3;
2103
            break;
2104
        case POWERPC_EXCP_BOOKE:
2105
            srr0 = SPR_BOOKE_MCSRR0;
2106
            srr1 = SPR_BOOKE_MCSRR1;
2107
            asrr0 = SPR_BOOKE_CSRR0;
2108
            asrr1 = SPR_BOOKE_CSRR1;
2109
            break;
2110
        default:
2111
            break;
2112
        }
2113
        goto store_next;
2114
    case POWERPC_EXCP_DSI:       /* Data storage exception                   */
2115
        LOG_EXCP("DSI exception: DSISR=" ADDRX" DAR=" ADDRX "\n",
2116
                    env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2117
        new_msr &= ~((target_ulong)1 << MSR_RI);
2118
        if (lpes1 == 0)
2119
            new_msr |= (target_ulong)MSR_HVB;
2120
        goto store_next;
2121
    case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
2122
        LOG_EXCP("ISI exception: msr=" ADDRX ", nip=" ADDRX "\n",
2123
                    msr, env->nip);
2124
        new_msr &= ~((target_ulong)1 << MSR_RI);
2125
        if (lpes1 == 0)
2126
            new_msr |= (target_ulong)MSR_HVB;
2127
        msr |= env->error_code;
2128
        goto store_next;
2129
    case POWERPC_EXCP_EXTERNAL:  /* External input                           */
2130
        new_msr &= ~((target_ulong)1 << MSR_RI);
2131
        if (lpes0 == 1)
2132
            new_msr |= (target_ulong)MSR_HVB;
2133
        goto store_next;
2134
    case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
2135
        new_msr &= ~((target_ulong)1 << MSR_RI);
2136
        if (lpes1 == 0)
2137
            new_msr |= (target_ulong)MSR_HVB;
2138
        /* XXX: this is false */
2139
        /* Get rS/rD and rA from faulting opcode */
2140
        env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2141
        goto store_current;
2142
    case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
2143
        switch (env->error_code & ~0xF) {
2144
        case POWERPC_EXCP_FP:
2145
            if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2146
                LOG_EXCP("Ignore floating point exception\n");
2147
                env->exception_index = POWERPC_EXCP_NONE;
2148
                env->error_code = 0;
2149
                return;
2150
            }
2151
            new_msr &= ~((target_ulong)1 << MSR_RI);
2152
            if (lpes1 == 0)
2153
                new_msr |= (target_ulong)MSR_HVB;
2154
            msr |= 0x00100000;
2155
            if (msr_fe0 == msr_fe1)
2156
                goto store_next;
2157
            msr |= 0x00010000;
2158
            break;
2159
        case POWERPC_EXCP_INVAL:
2160
            LOG_EXCP("Invalid instruction at " ADDRX "\n",
2161
                        env->nip);
2162
            new_msr &= ~((target_ulong)1 << MSR_RI);
2163
            if (lpes1 == 0)
2164
                new_msr |= (target_ulong)MSR_HVB;
2165
            msr |= 0x00080000;
2166
            break;
2167
        case POWERPC_EXCP_PRIV:
2168
            new_msr &= ~((target_ulong)1 << MSR_RI);
2169
            if (lpes1 == 0)
2170
                new_msr |= (target_ulong)MSR_HVB;
2171
            msr |= 0x00040000;
2172
            break;
2173
        case POWERPC_EXCP_TRAP:
2174
            new_msr &= ~((target_ulong)1 << MSR_RI);
2175
            if (lpes1 == 0)
2176
                new_msr |= (target_ulong)MSR_HVB;
2177
            msr |= 0x00020000;
2178
            break;
2179
        default:
2180
            /* Should never occur */
2181
            cpu_abort(env, "Invalid program exception %d. Aborting\n",
2182
                      env->error_code);
2183
            break;
2184
        }
2185
        goto store_current;
2186
    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
2187
        new_msr &= ~((target_ulong)1 << MSR_RI);
2188
        if (lpes1 == 0)
2189
            new_msr |= (target_ulong)MSR_HVB;
2190
        goto store_current;
2191
    case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
2192
        /* NOTE: this is a temporary hack to support graphics OSI
2193
           calls from the MOL driver */
2194
        /* XXX: To be removed */
2195
        if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
2196
            env->osi_call) {
2197
            if (env->osi_call(env) != 0) {
2198
                env->exception_index = POWERPC_EXCP_NONE;
2199
                env->error_code = 0;
2200
                return;
2201
            }
2202
        }
2203
        if (loglevel & CPU_LOG_INT) {
2204
            dump_syscall(env);
2205
        }
2206
        new_msr &= ~((target_ulong)1 << MSR_RI);
2207
        lev = env->error_code;
2208
        if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2209
            new_msr |= (target_ulong)MSR_HVB;
2210
        goto store_next;
2211
    case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
2212
        new_msr &= ~((target_ulong)1 << MSR_RI);
2213
        goto store_current;
2214
    case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
2215
        new_msr &= ~((target_ulong)1 << MSR_RI);
2216
        if (lpes1 == 0)
2217
            new_msr |= (target_ulong)MSR_HVB;
2218
        goto store_next;
2219
    case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
2220
        /* FIT on 4xx */
2221
        LOG_EXCP("FIT exception\n");
2222
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2223
        goto store_next;
2224
    case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
2225
        LOG_EXCP("WDT exception\n");
2226
        switch (excp_model) {
2227
        case POWERPC_EXCP_BOOKE:
2228
            srr0 = SPR_BOOKE_CSRR0;
2229
            srr1 = SPR_BOOKE_CSRR1;
2230
            break;
2231
        default:
2232
            break;
2233
        }
2234
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2235
        goto store_next;
2236
    case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
2237
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2238
        goto store_next;
2239
    case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
2240
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2241
        goto store_next;
2242
    case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
2243
        switch (excp_model) {
2244
        case POWERPC_EXCP_BOOKE:
2245
            srr0 = SPR_BOOKE_DSRR0;
2246
            srr1 = SPR_BOOKE_DSRR1;
2247
            asrr0 = SPR_BOOKE_CSRR0;
2248
            asrr1 = SPR_BOOKE_CSRR1;
2249
            break;
2250
        default:
2251
            break;
2252
        }
2253
        /* XXX: TODO */
2254
        cpu_abort(env, "Debug exception is not implemented yet !\n");
2255
        goto store_next;
2256
    case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
2257
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2258
        goto store_current;
2259
    case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
2260
        /* XXX: TODO */
2261
        cpu_abort(env, "Embedded floating point data exception "
2262
                  "is not implemented yet !\n");
2263
        goto store_next;
2264
    case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
2265
        /* XXX: TODO */
2266
        cpu_abort(env, "Embedded floating point round exception "
2267
                  "is not implemented yet !\n");
2268
        goto store_next;
2269
    case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
2270
        new_msr &= ~((target_ulong)1 << MSR_RI);
2271
        /* XXX: TODO */
2272
        cpu_abort(env,
2273
                  "Performance counter exception is not implemented yet !\n");
2274
        goto store_next;
2275
    case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
2276
        /* XXX: TODO */
2277
        cpu_abort(env,
2278
                  "Embedded doorbell interrupt is not implemented yet !\n");
2279
        goto store_next;
2280
    case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
2281
        switch (excp_model) {
2282
        case POWERPC_EXCP_BOOKE:
2283
            srr0 = SPR_BOOKE_CSRR0;
2284
            srr1 = SPR_BOOKE_CSRR1;
2285
            break;
2286
        default:
2287
            break;
2288
        }
2289
        /* XXX: TODO */
2290
        cpu_abort(env, "Embedded doorbell critical interrupt "
2291
                  "is not implemented yet !\n");
2292
        goto store_next;
2293
    case POWERPC_EXCP_RESET:     /* System reset exception                   */
2294
        new_msr &= ~((target_ulong)1 << MSR_RI);
2295
        if (0) {
2296
            /* XXX: find a suitable condition to enable the hypervisor mode */
2297
            new_msr |= (target_ulong)MSR_HVB;
2298
        }
2299
        goto store_next;
2300
    case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
2301
        new_msr &= ~((target_ulong)1 << MSR_RI);
2302
        if (lpes1 == 0)
2303
            new_msr |= (target_ulong)MSR_HVB;
2304
        goto store_next;
2305
    case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
2306
        new_msr &= ~((target_ulong)1 << MSR_RI);
2307
        if (lpes1 == 0)
2308
            new_msr |= (target_ulong)MSR_HVB;
2309
        goto store_next;
2310
    case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
2311
        srr0 = SPR_HSRR0;
2312
        srr1 = SPR_HSRR1;
2313
        new_msr |= (target_ulong)MSR_HVB;
2314
        goto store_next;
2315
    case POWERPC_EXCP_TRACE:     /* Trace exception                          */
2316
        new_msr &= ~((target_ulong)1 << MSR_RI);
2317
        if (lpes1 == 0)
2318
            new_msr |= (target_ulong)MSR_HVB;
2319
        goto store_next;
2320
    case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
2321
        srr0 = SPR_HSRR0;
2322
        srr1 = SPR_HSRR1;
2323
        new_msr |= (target_ulong)MSR_HVB;
2324
        goto store_next;
2325
    case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
2326
        srr0 = SPR_HSRR0;
2327
        srr1 = SPR_HSRR1;
2328
        new_msr |= (target_ulong)MSR_HVB;
2329
        goto store_next;
2330
    case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
2331
        srr0 = SPR_HSRR0;
2332
        srr1 = SPR_HSRR1;
2333
        new_msr |= (target_ulong)MSR_HVB;
2334
        goto store_next;
2335
    case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
2336
        srr0 = SPR_HSRR0;
2337
        srr1 = SPR_HSRR1;
2338
        new_msr |= (target_ulong)MSR_HVB;
2339
        goto store_next;
2340
    case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
2341
        new_msr &= ~((target_ulong)1 << MSR_RI);
2342
        if (lpes1 == 0)
2343
            new_msr |= (target_ulong)MSR_HVB;
2344
        goto store_current;
2345
    case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
2346
        LOG_EXCP("PIT exception\n");
2347
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2348
        goto store_next;
2349
    case POWERPC_EXCP_IO:        /* IO error exception                       */
2350
        /* XXX: TODO */
2351
        cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2352
        goto store_next;
2353
    case POWERPC_EXCP_RUNM:      /* Run mode exception                       */
2354
        /* XXX: TODO */
2355
        cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2356
        goto store_next;
2357
    case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 */
2358
        /* XXX: TODO */
2359
        cpu_abort(env, "602 emulation trap exception "
2360
                  "is not implemented yet !\n");
2361
        goto store_next;
2362
    case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
2363
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2364
        if (lpes1 == 0) /* XXX: check this */
2365
            new_msr |= (target_ulong)MSR_HVB;
2366
        switch (excp_model) {
2367
        case POWERPC_EXCP_602:
2368
        case POWERPC_EXCP_603:
2369
        case POWERPC_EXCP_603E:
2370
        case POWERPC_EXCP_G2:
2371
            goto tlb_miss_tgpr;
2372
        case POWERPC_EXCP_7x5:
2373
            goto tlb_miss;
2374
        case POWERPC_EXCP_74xx:
2375
            goto tlb_miss_74xx;
2376
        default:
2377
            cpu_abort(env, "Invalid instruction TLB miss exception\n");
2378
            break;
2379
        }
2380
        break;
2381
    case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
2382
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2383
        if (lpes1 == 0) /* XXX: check this */
2384
            new_msr |= (target_ulong)MSR_HVB;
2385
        switch (excp_model) {
2386
        case POWERPC_EXCP_602:
2387
        case POWERPC_EXCP_603:
2388
        case POWERPC_EXCP_603E:
2389
        case POWERPC_EXCP_G2:
2390
            goto tlb_miss_tgpr;
2391
        case POWERPC_EXCP_7x5:
2392
            goto tlb_miss;
2393
        case POWERPC_EXCP_74xx:
2394
            goto tlb_miss_74xx;
2395
        default:
2396
            cpu_abort(env, "Invalid data load TLB miss exception\n");
2397
            break;
2398
        }
2399
        break;
2400
    case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
2401
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2402
        if (lpes1 == 0) /* XXX: check this */
2403
            new_msr |= (target_ulong)MSR_HVB;
2404
        switch (excp_model) {
2405
        case POWERPC_EXCP_602:
2406
        case POWERPC_EXCP_603:
2407
        case POWERPC_EXCP_603E:
2408
        case POWERPC_EXCP_G2:
2409
        tlb_miss_tgpr:
2410
            /* Swap temporary saved registers with GPRs */
2411
            if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2412
                new_msr |= (target_ulong)1 << MSR_TGPR;
2413
                hreg_swap_gpr_tgpr(env);
2414
            }
2415
            goto tlb_miss;
2416
        case POWERPC_EXCP_7x5:
2417
        tlb_miss:
2418
#if defined (DEBUG_SOFTWARE_TLB)
2419
            if (loglevel != 0) {
2420
                const unsigned char *es;
2421
                target_ulong *miss, *cmp;
2422
                int en;
2423
                if (excp == POWERPC_EXCP_IFTLB) {
2424
                    es = "I";
2425
                    en = 'I';
2426
                    miss = &env->spr[SPR_IMISS];
2427
                    cmp = &env->spr[SPR_ICMP];
2428
                } else {
2429
                    if (excp == POWERPC_EXCP_DLTLB)
2430
                        es = "DL";
2431
                    else
2432
                        es = "DS";
2433
                    en = 'D';
2434
                    miss = &env->spr[SPR_DMISS];
2435
                    cmp = &env->spr[SPR_DCMP];
2436
                }
2437
                fprintf(logfile, "6xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
2438
                        " H1 " ADDRX " H2 " ADDRX " %08x\n",
2439
                        es, en, *miss, en, *cmp,
2440
                        env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2441
                        env->error_code);
2442
            }
2443
#endif
2444
            msr |= env->crf[0] << 28;
2445
            msr |= env->error_code; /* key, D/I, S/L bits */
2446
            /* Set way using a LRU mechanism */
2447
            msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2448
            break;
2449
        case POWERPC_EXCP_74xx:
2450
        tlb_miss_74xx:
2451
#if defined (DEBUG_SOFTWARE_TLB)
2452
            if (loglevel != 0) {
2453
                const unsigned char *es;
2454
                target_ulong *miss, *cmp;
2455
                int en;
2456
                if (excp == POWERPC_EXCP_IFTLB) {
2457
                    es = "I";
2458
                    en = 'I';
2459
                    miss = &env->spr[SPR_TLBMISS];
2460
                    cmp = &env->spr[SPR_PTEHI];
2461
                } else {
2462
                    if (excp == POWERPC_EXCP_DLTLB)
2463
                        es = "DL";
2464
                    else
2465
                        es = "DS";
2466
                    en = 'D';
2467
                    miss = &env->spr[SPR_TLBMISS];
2468
                    cmp = &env->spr[SPR_PTEHI];
2469
                }
2470
                fprintf(logfile, "74xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
2471
                        " %08x\n",
2472
                        es, en, *miss, en, *cmp, env->error_code);
2473
            }
2474
#endif
2475
            msr |= env->error_code; /* key bit */
2476
            break;
2477
        default:
2478
            cpu_abort(env, "Invalid data store TLB miss exception\n");
2479
            break;
2480
        }
2481
        goto store_next;
2482
    case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
2483
        /* XXX: TODO */
2484
        cpu_abort(env, "Floating point assist exception "
2485
                  "is not implemented yet !\n");
2486
        goto store_next;
2487
    case POWERPC_EXCP_DABR:      /* Data address breakpoint                  */
2488
        /* XXX: TODO */
2489
        cpu_abort(env, "DABR exception is not implemented yet !\n");
2490
        goto store_next;
2491
    case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
2492
        /* XXX: TODO */
2493
        cpu_abort(env, "IABR exception is not implemented yet !\n");
2494
        goto store_next;
2495
    case POWERPC_EXCP_SMI:       /* System management interrupt              */
2496
        /* XXX: TODO */
2497
        cpu_abort(env, "SMI exception is not implemented yet !\n");
2498
        goto store_next;
2499
    case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
2500
        /* XXX: TODO */
2501
        cpu_abort(env, "Thermal management exception "
2502
                  "is not implemented yet !\n");
2503
        goto store_next;
2504
    case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
2505
        new_msr &= ~((target_ulong)1 << MSR_RI);
2506
        if (lpes1 == 0)
2507
            new_msr |= (target_ulong)MSR_HVB;
2508
        /* XXX: TODO */
2509
        cpu_abort(env,
2510
                  "Performance counter exception is not implemented yet !\n");
2511
        goto store_next;
2512
    case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
2513
        /* XXX: TODO */
2514
        cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2515
        goto store_next;
2516
    case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
2517
        /* XXX: TODO */
2518
        cpu_abort(env,
2519
                  "970 soft-patch exception is not implemented yet !\n");
2520
        goto store_next;
2521
    case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
2522
        /* XXX: TODO */
2523
        cpu_abort(env,
2524
                  "970 maintenance exception is not implemented yet !\n");
2525
        goto store_next;
2526
    case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             */
2527
        /* XXX: TODO */
2528
        cpu_abort(env, "Maskable external exception "
2529
                  "is not implemented yet !\n");
2530
        goto store_next;
2531
    case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         */
2532
        /* XXX: TODO */
2533
        cpu_abort(env, "Non maskable external exception "
2534
                  "is not implemented yet !\n");
2535
        goto store_next;
2536
    default:
2537
    excp_invalid:
2538
        cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2539
        break;
2540
    store_current:
2541
        /* save current instruction location */
2542
        env->spr[srr0] = env->nip - 4;
2543
        break;
2544
    store_next:
2545
        /* save next instruction location */
2546
        env->spr[srr0] = env->nip;
2547
        break;
2548
    }
2549
    /* Save MSR */
2550
    env->spr[srr1] = msr;
2551
    /* If any alternate SRR register are defined, duplicate saved values */
2552
    if (asrr0 != -1)
2553
        env->spr[asrr0] = env->spr[srr0];
2554
    if (asrr1 != -1)
2555
        env->spr[asrr1] = env->spr[srr1];
2556
    /* If we disactivated any translation, flush TLBs */
2557
    if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2558
        tlb_flush(env, 1);
2559
    /* reload MSR with correct bits */
2560
    new_msr &= ~((target_ulong)1 << MSR_EE);
2561
    new_msr &= ~((target_ulong)1 << MSR_PR);
2562
    new_msr &= ~((target_ulong)1 << MSR_FP);
2563
    new_msr &= ~((target_ulong)1 << MSR_FE0);
2564
    new_msr &= ~((target_ulong)1 << MSR_SE);
2565
    new_msr &= ~((target_ulong)1 << MSR_BE);
2566
    new_msr &= ~((target_ulong)1 << MSR_FE1);
2567
    new_msr &= ~((target_ulong)1 << MSR_IR);
2568
    new_msr &= ~((target_ulong)1 << MSR_DR);
2569
#if 0 /* Fix this: not on all targets */
2570
    new_msr &= ~((target_ulong)1 << MSR_PMM);
2571
#endif
2572
    new_msr &= ~((target_ulong)1 << MSR_LE);
2573
    if (msr_ile)
2574
        new_msr |= (target_ulong)1 << MSR_LE;
2575
    else
2576
        new_msr &= ~((target_ulong)1 << MSR_LE);
2577
    /* Jump to handler */
2578
    vector = env->excp_vectors[excp];
2579
    if (vector == (target_ulong)-1ULL) {
2580
        cpu_abort(env, "Raised an exception without defined vector %d\n",
2581
                  excp);
2582
    }
2583
    vector |= env->excp_prefix;
2584
#if defined(TARGET_PPC64)
2585
    if (excp_model == POWERPC_EXCP_BOOKE) {
2586
        if (!msr_icm) {
2587
            new_msr &= ~((target_ulong)1 << MSR_CM);
2588
            vector = (uint32_t)vector;
2589
        } else {
2590
            new_msr |= (target_ulong)1 << MSR_CM;
2591
        }
2592
    } else {
2593
        if (!msr_isf) {
2594
            new_msr &= ~((target_ulong)1 << MSR_SF);
2595
            vector = (uint32_t)vector;
2596
        } else {
2597
            new_msr |= (target_ulong)1 << MSR_SF;
2598
        }
2599
    }
2600
#endif
2601
    /* XXX: we don't use hreg_store_msr here as already have treated
2602
     *      any special case that could occur. Just store MSR and update hflags
2603
     */
2604
    env->msr = new_msr & env->msr_mask;
2605
    hreg_compute_hflags(env);
2606
    env->nip = vector;
2607
    /* Reset exception state */
2608
    env->exception_index = POWERPC_EXCP_NONE;
2609
    env->error_code = 0;
2610
}
2611

    
2612
void do_interrupt (CPUState *env)
2613
{
2614
    powerpc_excp(env, env->excp_model, env->exception_index);
2615
}
2616

    
2617
void ppc_hw_interrupt (CPUPPCState *env)
2618
{
2619
    int hdice;
2620

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

    
2736
void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2737
{
2738
    FILE *f;
2739

    
2740
    if (logfile) {
2741
        f = logfile;
2742
    } else {
2743
        f = stdout;
2744
        return;
2745
    }
2746
    fprintf(f, "Return from exception at " ADDRX " with flags " ADDRX "\n",
2747
            RA, msr);
2748
}
2749

    
2750
void cpu_ppc_reset (void *opaque)
2751
{
2752
    CPUPPCState *env;
2753
    target_ulong msr;
2754

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

    
2790
CPUPPCState *cpu_ppc_init (const char *cpu_model)
2791
{
2792
    CPUPPCState *env;
2793
    const ppc_def_t *def;
2794

    
2795
    def = cpu_ppc_find_by_name(cpu_model);
2796
    if (!def)
2797
        return NULL;
2798

    
2799
    env = qemu_mallocz(sizeof(CPUPPCState));
2800
    if (!env)
2801
        return NULL;
2802
    cpu_exec_init(env);
2803
    ppc_translate_init();
2804
    env->cpu_model_str = cpu_model;
2805
    cpu_ppc_register_internal(env, def);
2806
    cpu_ppc_reset(env);
2807

    
2808
    if (kvm_enabled())
2809
        kvm_init_vcpu(env);
2810

    
2811
    return env;
2812
}
2813

    
2814
void cpu_ppc_close (CPUPPCState *env)
2815
{
2816
    /* Should also remove all opcode tables... */
2817
    qemu_free(env);
2818
}