Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ 5b52b991

History | View | Annotate | Download (91.4 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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

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

    
39
/*****************************************************************************/
40
/* PowerPC MMU emulation */
41

    
42
#if defined(CONFIG_USER_ONLY)
43
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
44
                              int mmu_idx, int is_softmmu)
45
{
46
    int exception, error_code;
47

    
48
    if (rw == 2) {
49
        exception = POWERPC_EXCP_ISI;
50
        error_code = 0x40000000;
51
    } else {
52
        exception = POWERPC_EXCP_DSI;
53
        error_code = 0x40000000;
54
        if (rw)
55
            error_code |= 0x02000000;
56
        env->spr[SPR_DAR] = address;
57
        env->spr[SPR_DSISR] = error_code;
58
    }
59
    env->exception_index = exception;
60
    env->error_code = error_code;
61

    
62
    return 1;
63
}
64

    
65
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
66
{
67
    return addr;
68
}
69

    
70
#else
71
/* Common routines used by software and hardware TLBs emulation */
72
static always_inline int pte_is_valid (target_ulong pte0)
73
{
74
    return pte0 & 0x80000000 ? 1 : 0;
75
}
76

    
77
static always_inline void pte_invalidate (target_ulong *pte0)
78
{
79
    *pte0 &= ~0x80000000;
80
}
81

    
82
#if defined(TARGET_PPC64)
83
static always_inline int pte64_is_valid (target_ulong pte0)
84
{
85
    return pte0 & 0x0000000000000001ULL ? 1 : 0;
86
}
87

    
88
static always_inline void pte64_invalidate (target_ulong *pte0)
89
{
90
    *pte0 &= ~0x0000000000000001ULL;
91
}
92
#endif
93

    
94
#define PTE_PTEM_MASK 0x7FFFFFBF
95
#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
96
#if defined(TARGET_PPC64)
97
#define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
98
#define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
99
#endif
100

    
101
static always_inline int pp_check (int key, int pp, int nx)
102
{
103
    int access;
104

    
105
    /* Compute access rights */
106
    /* When pp is 3/7, the result is undefined. Set it to noaccess */
107
    access = 0;
108
    if (key == 0) {
109
        switch (pp) {
110
        case 0x0:
111
        case 0x1:
112
        case 0x2:
113
            access |= PAGE_WRITE;
114
            /* No break here */
115
        case 0x3:
116
        case 0x6:
117
            access |= PAGE_READ;
118
            break;
119
        }
120
    } else {
121
        switch (pp) {
122
        case 0x0:
123
        case 0x6:
124
            access = 0;
125
            break;
126
        case 0x1:
127
        case 0x3:
128
            access = PAGE_READ;
129
            break;
130
        case 0x2:
131
            access = PAGE_READ | PAGE_WRITE;
132
            break;
133
        }
134
    }
135
    if (nx == 0)
136
        access |= PAGE_EXEC;
137

    
138
    return access;
139
}
140

    
141
static always_inline int check_prot (int prot, int rw, int access_type)
142
{
143
    int ret;
144

    
145
    if (access_type == ACCESS_CODE) {
146
        if (prot & PAGE_EXEC)
147
            ret = 0;
148
        else
149
            ret = -2;
150
    } else if (rw) {
151
        if (prot & PAGE_WRITE)
152
            ret = 0;
153
        else
154
            ret = -2;
155
    } else {
156
        if (prot & PAGE_READ)
157
            ret = 0;
158
        else
159
            ret = -2;
160
    }
161

    
162
    return ret;
163
}
164

    
165
static always_inline int _pte_check (mmu_ctx_t *ctx, int is_64b,
166
                                     target_ulong pte0, target_ulong pte1,
167
                                     int h, int rw, int type)
168
{
169
    target_ulong ptem, mmask;
170
    int access, ret, pteh, ptev, pp;
171

    
172
    access = 0;
173
    ret = -1;
174
    /* Check validity and table match */
175
#if defined(TARGET_PPC64)
176
    if (is_64b) {
177
        ptev = pte64_is_valid(pte0);
178
        pteh = (pte0 >> 1) & 1;
179
    } else
180
#endif
181
    {
182
        ptev = pte_is_valid(pte0);
183
        pteh = (pte0 >> 6) & 1;
184
    }
185
    if (ptev && h == pteh) {
186
        /* Check vsid & api */
187
#if defined(TARGET_PPC64)
188
        if (is_64b) {
189
            ptem = pte0 & PTE64_PTEM_MASK;
190
            mmask = PTE64_CHECK_MASK;
191
            pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
192
            ctx->nx |= (pte1 >> 2) & 1; /* No execute bit */
193
            ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
194
        } else
195
#endif
196
        {
197
            ptem = pte0 & PTE_PTEM_MASK;
198
            mmask = PTE_CHECK_MASK;
199
            pp = pte1 & 0x00000003;
200
        }
201
        if (ptem == ctx->ptem) {
202
            if (ctx->raddr != (target_ulong)-1) {
203
                /* all matches should have equal RPN, WIMG & PP */
204
                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
205
                    if (loglevel != 0)
206
                        fprintf(logfile, "Bad RPN/WIMG/PP\n");
207
                    return -3;
208
                }
209
            }
210
            /* Compute access rights */
211
            access = pp_check(ctx->key, pp, ctx->nx);
212
            /* Keep the matching PTE informations */
213
            ctx->raddr = pte1;
214
            ctx->prot = access;
215
            ret = check_prot(ctx->prot, rw, type);
216
            if (ret == 0) {
217
                /* Access granted */
218
#if defined (DEBUG_MMU)
219
                if (loglevel != 0)
220
                    fprintf(logfile, "PTE access granted !\n");
221
#endif
222
            } else {
223
                /* Access right violation */
224
#if defined (DEBUG_MMU)
225
                if (loglevel != 0)
226
                    fprintf(logfile, "PTE access rejected\n");
227
#endif
228
            }
229
        }
230
    }
231

    
232
    return ret;
233
}
234

    
235
static always_inline int pte32_check (mmu_ctx_t *ctx,
236
                                      target_ulong pte0, target_ulong pte1,
237
                                      int h, int rw, int type)
238
{
239
    return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
240
}
241

    
242
#if defined(TARGET_PPC64)
243
static always_inline int pte64_check (mmu_ctx_t *ctx,
244
                                      target_ulong pte0, target_ulong pte1,
245
                                      int h, int rw, int type)
246
{
247
    return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
248
}
249
#endif
250

    
251
static always_inline int pte_update_flags (mmu_ctx_t *ctx, target_ulong *pte1p,
252
                                           int ret, int rw)
253
{
254
    int store = 0;
255

    
256
    /* Update page flags */
257
    if (!(*pte1p & 0x00000100)) {
258
        /* Update accessed flag */
259
        *pte1p |= 0x00000100;
260
        store = 1;
261
    }
262
    if (!(*pte1p & 0x00000080)) {
263
        if (rw == 1 && ret == 0) {
264
            /* Update changed flag */
265
            *pte1p |= 0x00000080;
266
            store = 1;
267
        } else {
268
            /* Force page fault for first write access */
269
            ctx->prot &= ~PAGE_WRITE;
270
        }
271
    }
272

    
273
    return store;
274
}
275

    
276
/* Software driven TLB helpers */
277
static always_inline int ppc6xx_tlb_getnum (CPUState *env, target_ulong eaddr,
278
                                            int way, int is_code)
279
{
280
    int nr;
281

    
282
    /* Select TLB num in a way from address */
283
    nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
284
    /* Select TLB way */
285
    nr += env->tlb_per_way * way;
286
    /* 6xx have separate TLBs for instructions and data */
287
    if (is_code && env->id_tlbs == 1)
288
        nr += env->nb_tlb;
289

    
290
    return nr;
291
}
292

    
293
static always_inline void ppc6xx_tlb_invalidate_all (CPUState *env)
294
{
295
    ppc6xx_tlb_t *tlb;
296
    int nr, max;
297

    
298
#if defined (DEBUG_SOFTWARE_TLB) && 0
299
    if (loglevel != 0) {
300
        fprintf(logfile, "Invalidate all TLBs\n");
301
    }
302
#endif
303
    /* Invalidate all defined software TLB */
304
    max = env->nb_tlb;
305
    if (env->id_tlbs == 1)
306
        max *= 2;
307
    for (nr = 0; nr < max; nr++) {
308
        tlb = &env->tlb[nr].tlb6;
309
        pte_invalidate(&tlb->pte0);
310
    }
311
    tlb_flush(env, 1);
312
}
313

    
314
static always_inline void __ppc6xx_tlb_invalidate_virt (CPUState *env,
315
                                                        target_ulong eaddr,
316
                                                        int is_code,
317
                                                        int match_epn)
318
{
319
#if !defined(FLUSH_ALL_TLBS)
320
    ppc6xx_tlb_t *tlb;
321
    int way, nr;
322

    
323
    /* Invalidate ITLB + DTLB, all ways */
324
    for (way = 0; way < env->nb_ways; way++) {
325
        nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
326
        tlb = &env->tlb[nr].tlb6;
327
        if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
328
#if defined (DEBUG_SOFTWARE_TLB)
329
            if (loglevel != 0) {
330
                fprintf(logfile, "TLB invalidate %d/%d " ADDRX "\n",
331
                        nr, env->nb_tlb, eaddr);
332
            }
333
#endif
334
            pte_invalidate(&tlb->pte0);
335
            tlb_flush_page(env, tlb->EPN);
336
        }
337
    }
338
#else
339
    /* XXX: PowerPC specification say this is valid as well */
340
    ppc6xx_tlb_invalidate_all(env);
341
#endif
342
}
343

    
344
static always_inline void ppc6xx_tlb_invalidate_virt (CPUState *env,
345
                                                      target_ulong eaddr,
346
                                                      int is_code)
347
{
348
    __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
349
}
350

    
351
void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
352
                       target_ulong pte0, target_ulong pte1)
353
{
354
    ppc6xx_tlb_t *tlb;
355
    int nr;
356

    
357
    nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
358
    tlb = &env->tlb[nr].tlb6;
359
#if defined (DEBUG_SOFTWARE_TLB)
360
    if (loglevel != 0) {
361
        fprintf(logfile, "Set TLB %d/%d EPN " ADDRX " PTE0 " ADDRX
362
                " PTE1 " ADDRX "\n", nr, env->nb_tlb, EPN, pte0, pte1);
363
    }
364
#endif
365
    /* Invalidate any pending reference in Qemu for this virtual address */
366
    __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
367
    tlb->pte0 = pte0;
368
    tlb->pte1 = pte1;
369
    tlb->EPN = EPN;
370
    /* Store last way for LRU mechanism */
371
    env->last_way = way;
372
}
373

    
374
static always_inline int ppc6xx_tlb_check (CPUState *env, mmu_ctx_t *ctx,
375
                                           target_ulong eaddr, int rw,
376
                                           int access_type)
377
{
378
    ppc6xx_tlb_t *tlb;
379
    int nr, best, way;
380
    int ret;
381

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

    
447
    return ret;
448
}
449

    
450
/* Perform BAT hit & translation */
451
static always_inline int get_bat (CPUState *env, mmu_ctx_t *ctx,
452
                                  target_ulong virtual, int rw, int type)
453
{
454
    target_ulong *BATlt, *BATut, *BATu, *BATl;
455
    target_ulong base, BEPIl, BEPIu, bl;
456
    int i, pp, pr;
457
    int ret = -1;
458

    
459
#if defined (DEBUG_BATS)
460
    if (loglevel != 0) {
461
        fprintf(logfile, "%s: %cBAT v 0x" ADDRX "\n", __func__,
462
                type == ACCESS_CODE ? 'I' : 'D', virtual);
463
    }
464
#endif
465
    pr = msr_pr;
466
    switch (type) {
467
    case ACCESS_CODE:
468
        BATlt = env->IBAT[1];
469
        BATut = env->IBAT[0];
470
        break;
471
    default:
472
        BATlt = env->DBAT[1];
473
        BATut = env->DBAT[0];
474
        break;
475
    }
476
#if defined (DEBUG_BATS)
477
    if (loglevel != 0) {
478
        fprintf(logfile, "%s...: %cBAT v 0x" ADDRX "\n", __func__,
479
                type == ACCESS_CODE ? 'I' : 'D', virtual);
480
    }
481
#endif
482
    base = virtual & 0xFFFC0000;
483
    for (i = 0; i < 4; i++) {
484
        BATu = &BATut[i];
485
        BATl = &BATlt[i];
486
        BEPIu = *BATu & 0xF0000000;
487
        BEPIl = *BATu & 0x0FFE0000;
488
        bl = (*BATu & 0x00001FFC) << 15;
489
#if defined (DEBUG_BATS)
490
        if (loglevel != 0) {
491
            fprintf(logfile, "%s: %cBAT%d v 0x" ADDRX " BATu 0x" ADDRX
492
                    " BATl 0x" ADDRX "\n",
493
                    __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
494
                    *BATu, *BATl);
495
        }
496
#endif
497
        if ((virtual & 0xF0000000) == BEPIu &&
498
            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
499
            /* BAT matches */
500
            if (((pr == 0) && (*BATu & 0x00000002)) ||
501
                ((pr != 0) && (*BATu & 0x00000001))) {
502
                /* Get physical address */
503
                ctx->raddr = (*BATl & 0xF0000000) |
504
                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
505
                    (virtual & 0x0001F000);
506
                /* Compute access rights */
507
                pp = *BATl & 0x00000003;
508
                ctx->prot = 0;
509
                if (pp != 0) {
510
                    ctx->prot = PAGE_READ | PAGE_EXEC;
511
                    if (pp == 0x2)
512
                        ctx->prot |= PAGE_WRITE;
513
                }
514
                ret = check_prot(ctx->prot, rw, type);
515
#if defined (DEBUG_BATS)
516
                if (ret == 0 && loglevel != 0) {
517
                    fprintf(logfile, "BAT %d match: r 0x" PADDRX
518
                            " prot=%c%c\n",
519
                            i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
520
                            ctx->prot & PAGE_WRITE ? 'W' : '-');
521
                }
522
#endif
523
                break;
524
            }
525
        }
526
    }
527
    if (ret < 0) {
528
#if defined (DEBUG_BATS)
529
        if (loglevel != 0) {
530
            fprintf(logfile, "no BAT match for 0x" ADDRX ":\n", virtual);
531
            for (i = 0; i < 4; i++) {
532
                BATu = &BATut[i];
533
                BATl = &BATlt[i];
534
                BEPIu = *BATu & 0xF0000000;
535
                BEPIl = *BATu & 0x0FFE0000;
536
                bl = (*BATu & 0x00001FFC) << 15;
537
                fprintf(logfile, "%s: %cBAT%d v 0x" ADDRX " BATu 0x" ADDRX
538
                        " BATl 0x" ADDRX " \n\t"
539
                        "0x" ADDRX " 0x" ADDRX " 0x" ADDRX "\n",
540
                        __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
541
                        *BATu, *BATl, BEPIu, BEPIl, bl);
542
            }
543
        }
544
#endif
545
    }
546

    
547
    /* No hit */
548
    return ret;
549
}
550

    
551
/* PTE table lookup */
552
static always_inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h,
553
                                    int rw, int type)
554
{
555
    target_ulong base, pte0, pte1;
556
    int i, good = -1;
557
    int ret, r;
558

    
559
    ret = -1; /* No entry found */
560
    base = ctx->pg_addr[h];
561
    for (i = 0; i < 8; i++) {
562
#if defined(TARGET_PPC64)
563
        if (is_64b) {
564
            pte0 = ldq_phys(base + (i * 16));
565
            pte1 =  ldq_phys(base + (i * 16) + 8);
566
            r = pte64_check(ctx, pte0, pte1, h, rw, type);
567
#if defined (DEBUG_MMU)
568
            if (loglevel != 0) {
569
                fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX
570
                        " 0x" ADDRX " %d %d %d 0x" ADDRX "\n",
571
                        base + (i * 16), pte0, pte1,
572
                        (int)(pte0 & 1), h, (int)((pte0 >> 1) & 1),
573
                        ctx->ptem);
574
            }
575
#endif
576
        } else
577
#endif
578
        {
579
            pte0 = ldl_phys(base + (i * 8));
580
            pte1 =  ldl_phys(base + (i * 8) + 4);
581
            r = pte32_check(ctx, pte0, pte1, h, rw, type);
582
#if defined (DEBUG_MMU)
583
            if (loglevel != 0) {
584
                fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX
585
                        " 0x" ADDRX " %d %d %d 0x" ADDRX "\n",
586
                        base + (i * 8), pte0, pte1,
587
                        (int)(pte0 >> 31), h, (int)((pte0 >> 6) & 1),
588
                        ctx->ptem);
589
            }
590
#endif
591
        }
592
        switch (r) {
593
        case -3:
594
            /* PTE inconsistency */
595
            return -1;
596
        case -2:
597
            /* Access violation */
598
            ret = -2;
599
            good = i;
600
            break;
601
        case -1:
602
        default:
603
            /* No PTE match */
604
            break;
605
        case 0:
606
            /* access granted */
607
            /* XXX: we should go on looping to check all PTEs consistency
608
             *      but if we can speed-up the whole thing as the
609
             *      result would be undefined if PTEs are not consistent.
610
             */
611
            ret = 0;
612
            good = i;
613
            goto done;
614
        }
615
    }
616
    if (good != -1) {
617
    done:
618
#if defined (DEBUG_MMU)
619
        if (loglevel != 0) {
620
            fprintf(logfile, "found PTE at addr 0x" PADDRX " prot=0x%01x "
621
                    "ret=%d\n",
622
                    ctx->raddr, ctx->prot, ret);
623
        }
624
#endif
625
        /* Update page flags */
626
        pte1 = ctx->raddr;
627
        if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
628
#if defined(TARGET_PPC64)
629
            if (is_64b) {
630
                stq_phys_notdirty(base + (good * 16) + 8, pte1);
631
            } else
632
#endif
633
            {
634
                stl_phys_notdirty(base + (good * 8) + 4, pte1);
635
            }
636
        }
637
    }
638

    
639
    return ret;
640
}
641

    
642
static always_inline int find_pte32 (mmu_ctx_t *ctx, int h, int rw, int type)
643
{
644
    return _find_pte(ctx, 0, h, rw, type);
645
}
646

    
647
#if defined(TARGET_PPC64)
648
static always_inline int find_pte64 (mmu_ctx_t *ctx, int h, int rw, int type)
649
{
650
    return _find_pte(ctx, 1, h, rw, type);
651
}
652
#endif
653

    
654
static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx,
655
                                   int h, int rw, int type)
656
{
657
#if defined(TARGET_PPC64)
658
    if (env->mmu_model == POWERPC_MMU_64B)
659
        return find_pte64(ctx, h, rw, type);
660
#endif
661

    
662
    return find_pte32(ctx, h, rw, type);
663
}
664

    
665
#if defined(TARGET_PPC64)
666
static always_inline int slb_is_valid (uint64_t slb64)
667
{
668
    return slb64 & 0x0000000008000000ULL ? 1 : 0;
669
}
670

    
671
static always_inline void slb_invalidate (uint64_t *slb64)
672
{
673
    *slb64 &= ~0x0000000008000000ULL;
674
}
675

    
676
static always_inline int slb_lookup (CPUPPCState *env, target_ulong eaddr,
677
                                     target_ulong *vsid,
678
                                     target_ulong *page_mask, int *attr)
679
{
680
    target_phys_addr_t sr_base;
681
    target_ulong mask;
682
    uint64_t tmp64;
683
    uint32_t tmp;
684
    int n, ret;
685

    
686
    ret = -5;
687
    sr_base = env->spr[SPR_ASR];
688
#if defined(DEBUG_SLB)
689
    if (loglevel != 0) {
690
        fprintf(logfile, "%s: eaddr " ADDRX " base " PADDRX "\n",
691
                __func__, eaddr, sr_base);
692
    }
693
#endif
694
    mask = 0x0000000000000000ULL; /* Avoid gcc warning */
695
    for (n = 0; n < env->slb_nr; n++) {
696
        tmp64 = ldq_phys(sr_base);
697
        tmp = ldl_phys(sr_base + 8);
698
#if defined(DEBUG_SLB)
699
        if (loglevel != 0) {
700
            fprintf(logfile, "%s: seg %d " PADDRX " %016" PRIx64 " %08"
701
                    PRIx32 "\n", __func__, n, sr_base, tmp64, tmp);
702
        }
703
#endif
704
        if (slb_is_valid(tmp64)) {
705
            /* SLB entry is valid */
706
            switch (tmp64 & 0x0000000006000000ULL) {
707
            case 0x0000000000000000ULL:
708
                /* 256 MB segment */
709
                mask = 0xFFFFFFFFF0000000ULL;
710
                break;
711
            case 0x0000000002000000ULL:
712
                /* 1 TB segment */
713
                mask = 0xFFFF000000000000ULL;
714
                break;
715
            case 0x0000000004000000ULL:
716
            case 0x0000000006000000ULL:
717
                /* Reserved => segment is invalid */
718
                continue;
719
            }
720
            if ((eaddr & mask) == (tmp64 & mask)) {
721
                /* SLB match */
722
                *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
723
                *page_mask = ~mask;
724
                *attr = tmp & 0xFF;
725
                ret = n;
726
                break;
727
            }
728
        }
729
        sr_base += 12;
730
    }
731

    
732
    return ret;
733
}
734

    
735
void ppc_slb_invalidate_all (CPUPPCState *env)
736
{
737
    target_phys_addr_t sr_base;
738
    uint64_t tmp64;
739
    int n, do_invalidate;
740

    
741
    do_invalidate = 0;
742
    sr_base = env->spr[SPR_ASR];
743
    /* XXX: Warning: slbia never invalidates the first segment */
744
    for (n = 1; n < env->slb_nr; n++) {
745
        tmp64 = ldq_phys(sr_base);
746
        if (slb_is_valid(tmp64)) {
747
            slb_invalidate(&tmp64);
748
            stq_phys(sr_base, tmp64);
749
            /* XXX: given the fact that segment size is 256 MB or 1TB,
750
             *      and we still don't have a tlb_flush_mask(env, n, mask)
751
             *      in Qemu, we just invalidate all TLBs
752
             */
753
            do_invalidate = 1;
754
        }
755
        sr_base += 12;
756
    }
757
    if (do_invalidate)
758
        tlb_flush(env, 1);
759
}
760

    
761
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
762
{
763
    target_phys_addr_t sr_base;
764
    target_ulong vsid, page_mask;
765
    uint64_t tmp64;
766
    int attr;
767
    int n;
768

    
769
    n = slb_lookup(env, T0, &vsid, &page_mask, &attr);
770
    if (n >= 0) {
771
        sr_base = env->spr[SPR_ASR];
772
        sr_base += 12 * n;
773
        tmp64 = ldq_phys(sr_base);
774
        if (slb_is_valid(tmp64)) {
775
            slb_invalidate(&tmp64);
776
            stq_phys(sr_base, tmp64);
777
            /* XXX: given the fact that segment size is 256 MB or 1TB,
778
             *      and we still don't have a tlb_flush_mask(env, n, mask)
779
             *      in Qemu, we just invalidate all TLBs
780
             */
781
            tlb_flush(env, 1);
782
        }
783
    }
784
}
785

    
786
target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
787
{
788
    target_phys_addr_t sr_base;
789
    target_ulong rt;
790
    uint64_t tmp64;
791
    uint32_t tmp;
792

    
793
    sr_base = env->spr[SPR_ASR];
794
    sr_base += 12 * slb_nr;
795
    tmp64 = ldq_phys(sr_base);
796
    tmp = ldl_phys(sr_base + 8);
797
    if (tmp64 & 0x0000000008000000ULL) {
798
        /* SLB entry is valid */
799
        /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
800
        rt = tmp >> 8;             /* 65:88 => 40:63 */
801
        rt |= (tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
802
        /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
803
        rt |= ((tmp >> 4) & 0xF) << 27;
804
    } else {
805
        rt = 0;
806
    }
807
#if defined(DEBUG_SLB)
808
    if (loglevel != 0) {
809
        fprintf(logfile, "%s: " PADDRX " %016" PRIx64 " %08" PRIx32 " => %d "
810
                ADDRX "\n", __func__, sr_base, tmp64, tmp, slb_nr, rt);
811
    }
812
#endif
813

    
814
    return rt;
815
}
816

    
817
void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs)
818
{
819
    target_phys_addr_t sr_base;
820
    uint64_t tmp64;
821
    uint32_t tmp;
822

    
823
    sr_base = env->spr[SPR_ASR];
824
    sr_base += 12 * slb_nr;
825
    /* Copy Rs bits 37:63 to SLB 62:88 */
826
    tmp = rs << 8;
827
    tmp64 = (rs >> 24) & 0x7;
828
    /* Copy Rs bits 33:36 to SLB 89:92 */
829
    tmp |= ((rs >> 27) & 0xF) << 4;
830
    /* Set the valid bit */
831
    tmp64 |= 1 << 27;
832
    /* Set ESID */
833
    tmp64 |= (uint32_t)slb_nr << 28;
834
#if defined(DEBUG_SLB)
835
    if (loglevel != 0) {
836
        fprintf(logfile, "%s: %d " ADDRX " => " PADDRX " %016" PRIx64 " %08"
837
                PRIx32 "\n", __func__, slb_nr, rs, sr_base, tmp64, tmp);
838
    }
839
#endif
840
    /* Write SLB entry to memory */
841
    stq_phys(sr_base, tmp64);
842
    stl_phys(sr_base + 8, tmp);
843
}
844
#endif /* defined(TARGET_PPC64) */
845

    
846
/* Perform segment based translation */
847
static always_inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
848
                                                    int sdr_sh,
849
                                                    target_phys_addr_t hash,
850
                                                    target_phys_addr_t mask)
851
{
852
    return (sdr1 & ((target_ulong)(-1ULL) << sdr_sh)) | (hash & mask);
853
}
854

    
855
static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
856
                                      target_ulong eaddr, int rw, int type)
857
{
858
    target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
859
    target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
860
#if defined(TARGET_PPC64)
861
    int attr;
862
#endif
863
    int ds, vsid_sh, sdr_sh, pr;
864
    int ret, ret2;
865

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

    
1067
    return ret;
1068
}
1069

    
1070
/* Generic TLB check function for embedded PowerPC implementations */
1071
static always_inline int ppcemb_tlb_check (CPUState *env, ppcemb_tlb_t *tlb,
1072
                                           target_phys_addr_t *raddrp,
1073
                                           target_ulong address,
1074
                                           uint32_t pid, int ext, int i)
1075
{
1076
    target_ulong mask;
1077

    
1078
    /* Check valid flag */
1079
    if (!(tlb->prot & PAGE_VALID)) {
1080
        if (loglevel != 0)
1081
            fprintf(logfile, "%s: TLB %d not valid\n", __func__, i);
1082
        return -1;
1083
    }
1084
    mask = ~(tlb->size - 1);
1085
#if defined (DEBUG_SOFTWARE_TLB)
1086
    if (loglevel != 0) {
1087
        fprintf(logfile, "%s: TLB %d address " ADDRX " PID %d <=> "
1088
                ADDRX " " ADDRX " %d\n",
1089
                __func__, i, address, pid, tlb->EPN, mask, (int)tlb->PID);
1090
    }
1091
#endif
1092
    /* Check PID */
1093
    if (tlb->PID != 0 && tlb->PID != pid)
1094
        return -1;
1095
    /* Check effective address */
1096
    if ((address & mask) != tlb->EPN)
1097
        return -1;
1098
    *raddrp = (tlb->RPN & mask) | (address & ~mask);
1099
#if (TARGET_PHYS_ADDR_BITS >= 36)
1100
    if (ext) {
1101
        /* Extend the physical address to 36 bits */
1102
        *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1103
    }
1104
#endif
1105

    
1106
    return 0;
1107
}
1108

    
1109
/* Generic TLB search function for PowerPC embedded implementations */
1110
int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1111
{
1112
    ppcemb_tlb_t *tlb;
1113
    target_phys_addr_t raddr;
1114
    int i, ret;
1115

    
1116
    /* Default return value is no match */
1117
    ret = -1;
1118
    for (i = 0; i < env->nb_tlb; i++) {
1119
        tlb = &env->tlb[i].tlbe;
1120
        if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1121
            ret = i;
1122
            break;
1123
        }
1124
    }
1125

    
1126
    return ret;
1127
}
1128

    
1129
/* Helpers specific to PowerPC 40x implementations */
1130
static always_inline void ppc4xx_tlb_invalidate_all (CPUState *env)
1131
{
1132
    ppcemb_tlb_t *tlb;
1133
    int i;
1134

    
1135
    for (i = 0; i < env->nb_tlb; i++) {
1136
        tlb = &env->tlb[i].tlbe;
1137
        tlb->prot &= ~PAGE_VALID;
1138
    }
1139
    tlb_flush(env, 1);
1140
}
1141

    
1142
static always_inline void ppc4xx_tlb_invalidate_virt (CPUState *env,
1143
                                                      target_ulong eaddr,
1144
                                                      uint32_t pid)
1145
{
1146
#if !defined(FLUSH_ALL_TLBS)
1147
    ppcemb_tlb_t *tlb;
1148
    target_phys_addr_t raddr;
1149
    target_ulong page, end;
1150
    int i;
1151

    
1152
    for (i = 0; i < env->nb_tlb; i++) {
1153
        tlb = &env->tlb[i].tlbe;
1154
        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1155
            end = tlb->EPN + tlb->size;
1156
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1157
                tlb_flush_page(env, page);
1158
            tlb->prot &= ~PAGE_VALID;
1159
            break;
1160
        }
1161
    }
1162
#else
1163
    ppc4xx_tlb_invalidate_all(env);
1164
#endif
1165
}
1166

    
1167
int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1168
                                 target_ulong address, int rw, int access_type)
1169
{
1170
    ppcemb_tlb_t *tlb;
1171
    target_phys_addr_t raddr;
1172
    int i, ret, zsel, zpr, pr;
1173

    
1174
    ret = -1;
1175
    raddr = -1;
1176
    pr = msr_pr;
1177
    for (i = 0; i < env->nb_tlb; i++) {
1178
        tlb = &env->tlb[i].tlbe;
1179
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1180
                             env->spr[SPR_40x_PID], 0, i) < 0)
1181
            continue;
1182
        zsel = (tlb->attr >> 4) & 0xF;
1183
        zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
1184
#if defined (DEBUG_SOFTWARE_TLB)
1185
        if (loglevel != 0) {
1186
            fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1187
                    __func__, i, zsel, zpr, rw, tlb->attr);
1188
        }
1189
#endif
1190
        /* Check execute enable bit */
1191
        switch (zpr) {
1192
        case 0x2:
1193
            if (pr != 0)
1194
                goto check_perms;
1195
            /* No break here */
1196
        case 0x3:
1197
            /* All accesses granted */
1198
            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1199
            ret = 0;
1200
            break;
1201
        case 0x0:
1202
            if (pr != 0) {
1203
                ctx->prot = 0;
1204
                ret = -2;
1205
                break;
1206
            }
1207
            /* No break here */
1208
        case 0x1:
1209
        check_perms:
1210
            /* Check from TLB entry */
1211
            /* XXX: there is a problem here or in the TLB fill code... */
1212
            ctx->prot = tlb->prot;
1213
            ctx->prot |= PAGE_EXEC;
1214
            ret = check_prot(ctx->prot, rw, access_type);
1215
            break;
1216
        }
1217
        if (ret >= 0) {
1218
            ctx->raddr = raddr;
1219
#if defined (DEBUG_SOFTWARE_TLB)
1220
            if (loglevel != 0) {
1221
                fprintf(logfile, "%s: access granted " ADDRX " => " REGX
1222
                        " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1223
                        ret);
1224
            }
1225
#endif
1226
            return 0;
1227
        }
1228
    }
1229
#if defined (DEBUG_SOFTWARE_TLB)
1230
    if (loglevel != 0) {
1231
        fprintf(logfile, "%s: access refused " ADDRX " => " REGX
1232
                " %d %d\n", __func__, address, raddr, ctx->prot,
1233
                ret);
1234
    }
1235
#endif
1236

    
1237
    return ret;
1238
}
1239

    
1240
void store_40x_sler (CPUPPCState *env, uint32_t val)
1241
{
1242
    /* XXX: TO BE FIXED */
1243
    if (val != 0x00000000) {
1244
        cpu_abort(env, "Little-endian regions are not supported by now\n");
1245
    }
1246
    env->spr[SPR_405_SLER] = val;
1247
}
1248

    
1249
int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1250
                                   target_ulong address, int rw,
1251
                                   int access_type)
1252
{
1253
    ppcemb_tlb_t *tlb;
1254
    target_phys_addr_t raddr;
1255
    int i, prot, ret;
1256

    
1257
    ret = -1;
1258
    raddr = -1;
1259
    for (i = 0; i < env->nb_tlb; i++) {
1260
        tlb = &env->tlb[i].tlbe;
1261
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1262
                             env->spr[SPR_BOOKE_PID], 1, i) < 0)
1263
            continue;
1264
        if (msr_pr != 0)
1265
            prot = tlb->prot & 0xF;
1266
        else
1267
            prot = (tlb->prot >> 4) & 0xF;
1268
        /* Check the address space */
1269
        if (access_type == ACCESS_CODE) {
1270
            if (msr_ir != (tlb->attr & 1))
1271
                continue;
1272
            ctx->prot = prot;
1273
            if (prot & PAGE_EXEC) {
1274
                ret = 0;
1275
                break;
1276
            }
1277
            ret = -3;
1278
        } else {
1279
            if (msr_dr != (tlb->attr & 1))
1280
                continue;
1281
            ctx->prot = prot;
1282
            if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
1283
                ret = 0;
1284
                break;
1285
            }
1286
            ret = -2;
1287
        }
1288
    }
1289
    if (ret >= 0)
1290
        ctx->raddr = raddr;
1291

    
1292
    return ret;
1293
}
1294

    
1295
static always_inline int check_physical (CPUState *env, mmu_ctx_t *ctx,
1296
                                         target_ulong eaddr, int rw)
1297
{
1298
    int in_plb, ret;
1299

    
1300
    ctx->raddr = eaddr;
1301
    ctx->prot = PAGE_READ | PAGE_EXEC;
1302
    ret = 0;
1303
    switch (env->mmu_model) {
1304
    case POWERPC_MMU_32B:
1305
    case POWERPC_MMU_SOFT_6xx:
1306
    case POWERPC_MMU_SOFT_74xx:
1307
    case POWERPC_MMU_SOFT_4xx:
1308
    case POWERPC_MMU_REAL_4xx:
1309
    case POWERPC_MMU_BOOKE:
1310
        ctx->prot |= PAGE_WRITE;
1311
        break;
1312
#if defined(TARGET_PPC64)
1313
    case POWERPC_MMU_64B:
1314
        /* Real address are 60 bits long */
1315
        ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1316
        ctx->prot |= PAGE_WRITE;
1317
        break;
1318
#endif
1319
    case POWERPC_MMU_SOFT_4xx_Z:
1320
        if (unlikely(msr_pe != 0)) {
1321
            /* 403 family add some particular protections,
1322
             * using PBL/PBU registers for accesses with no translation.
1323
             */
1324
            in_plb =
1325
                /* Check PLB validity */
1326
                (env->pb[0] < env->pb[1] &&
1327
                 /* and address in plb area */
1328
                 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1329
                (env->pb[2] < env->pb[3] &&
1330
                 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1331
            if (in_plb ^ msr_px) {
1332
                /* Access in protected area */
1333
                if (rw == 1) {
1334
                    /* Access is not allowed */
1335
                    ret = -2;
1336
                }
1337
            } else {
1338
                /* Read-write access is allowed */
1339
                ctx->prot |= PAGE_WRITE;
1340
            }
1341
        }
1342
        break;
1343
    case POWERPC_MMU_BOOKE_FSL:
1344
        /* XXX: TODO */
1345
        cpu_abort(env, "BookE FSL MMU model not implemented\n");
1346
        break;
1347
    default:
1348
        cpu_abort(env, "Unknown or invalid MMU model\n");
1349
        return -1;
1350
    }
1351

    
1352
    return ret;
1353
}
1354

    
1355
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1356
                          int rw, int access_type, int check_BATs)
1357
{
1358
    int ret;
1359

    
1360
#if 0
1361
    if (loglevel != 0) {
1362
        fprintf(logfile, "%s\n", __func__);
1363
    }
1364
#endif
1365
    if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1366
        (access_type != ACCESS_CODE && msr_dr == 0)) {
1367
        /* No address translation */
1368
        ret = check_physical(env, ctx, eaddr, rw);
1369
    } else {
1370
        ret = -1;
1371
        switch (env->mmu_model) {
1372
        case POWERPC_MMU_32B:
1373
        case POWERPC_MMU_SOFT_6xx:
1374
        case POWERPC_MMU_SOFT_74xx:
1375
            /* Try to find a BAT */
1376
            if (check_BATs)
1377
                ret = get_bat(env, ctx, eaddr, rw, access_type);
1378
            /* No break here */
1379
#if defined(TARGET_PPC64)
1380
        case POWERPC_MMU_64B:
1381
#endif
1382
            if (ret < 0) {
1383
                /* We didn't match any BAT entry or don't have BATs */
1384
                ret = get_segment(env, ctx, eaddr, rw, access_type);
1385
            }
1386
            break;
1387
        case POWERPC_MMU_SOFT_4xx:
1388
        case POWERPC_MMU_SOFT_4xx_Z:
1389
            ret = mmu40x_get_physical_address(env, ctx, eaddr,
1390
                                              rw, access_type);
1391
            break;
1392
        case POWERPC_MMU_BOOKE:
1393
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1394
                                                rw, access_type);
1395
            break;
1396
        case POWERPC_MMU_BOOKE_FSL:
1397
            /* XXX: TODO */
1398
            cpu_abort(env, "BookE FSL MMU model not implemented\n");
1399
            return -1;
1400
        case POWERPC_MMU_REAL_4xx:
1401
            cpu_abort(env, "PowerPC 401 does not do any translation\n");
1402
            return -1;
1403
        default:
1404
            cpu_abort(env, "Unknown or invalid MMU model\n");
1405
            return -1;
1406
        }
1407
    }
1408
#if 0
1409
    if (loglevel != 0) {
1410
        fprintf(logfile, "%s address " ADDRX " => %d " PADDRX "\n",
1411
                __func__, eaddr, ret, ctx->raddr);
1412
    }
1413
#endif
1414

    
1415
    return ret;
1416
}
1417

    
1418
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1419
{
1420
    mmu_ctx_t ctx;
1421

    
1422
    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT, 1) != 0))
1423
        return -1;
1424

    
1425
    return ctx.raddr & TARGET_PAGE_MASK;
1426
}
1427

    
1428
/* Perform address translation */
1429
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1430
                              int mmu_idx, int is_softmmu)
1431
{
1432
    mmu_ctx_t ctx;
1433
    int access_type;
1434
    int ret = 0;
1435

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

    
1663
    return ret;
1664
}
1665

    
1666
/*****************************************************************************/
1667
/* BATs management */
1668
#if !defined(FLUSH_ALL_TLBS)
1669
static always_inline void do_invalidate_BAT (CPUPPCState *env,
1670
                                             target_ulong BATu,
1671
                                             target_ulong mask)
1672
{
1673
    target_ulong base, end, page;
1674

    
1675
    base = BATu & ~0x0001FFFF;
1676
    end = base + mask + 0x00020000;
1677
#if defined (DEBUG_BATS)
1678
    if (loglevel != 0) {
1679
        fprintf(logfile, "Flush BAT from " ADDRX " to " ADDRX " (" ADDRX ")\n",
1680
                base, end, mask);
1681
    }
1682
#endif
1683
    for (page = base; page != end; page += TARGET_PAGE_SIZE)
1684
        tlb_flush_page(env, page);
1685
#if defined (DEBUG_BATS)
1686
    if (loglevel != 0)
1687
        fprintf(logfile, "Flush done\n");
1688
#endif
1689
}
1690
#endif
1691

    
1692
static always_inline void dump_store_bat (CPUPPCState *env, char ID,
1693
                                          int ul, int nr, target_ulong value)
1694
{
1695
#if defined (DEBUG_BATS)
1696
    if (loglevel != 0) {
1697
        fprintf(logfile, "Set %cBAT%d%c to 0x" ADDRX " (0x" ADDRX ")\n",
1698
                ID, nr, ul == 0 ? 'u' : 'l', value, env->nip);
1699
    }
1700
#endif
1701
}
1702

    
1703
target_ulong do_load_ibatu (CPUPPCState *env, int nr)
1704
{
1705
    return env->IBAT[0][nr];
1706
}
1707

    
1708
target_ulong do_load_ibatl (CPUPPCState *env, int nr)
1709
{
1710
    return env->IBAT[1][nr];
1711
}
1712

    
1713
void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1714
{
1715
    target_ulong mask;
1716

    
1717
    dump_store_bat(env, 'I', 0, nr, value);
1718
    if (env->IBAT[0][nr] != value) {
1719
        mask = (value << 15) & 0x0FFE0000UL;
1720
#if !defined(FLUSH_ALL_TLBS)
1721
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1722
#endif
1723
        /* When storing valid upper BAT, mask BEPI and BRPN
1724
         * and invalidate all TLBs covered by this BAT
1725
         */
1726
        mask = (value << 15) & 0x0FFE0000UL;
1727
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1728
            (value & ~0x0001FFFFUL & ~mask);
1729
        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1730
            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1731
#if !defined(FLUSH_ALL_TLBS)
1732
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1733
#else
1734
        tlb_flush(env, 1);
1735
#endif
1736
    }
1737
}
1738

    
1739
void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1740
{
1741
    dump_store_bat(env, 'I', 1, nr, value);
1742
    env->IBAT[1][nr] = value;
1743
}
1744

    
1745
target_ulong do_load_dbatu (CPUPPCState *env, int nr)
1746
{
1747
    return env->DBAT[0][nr];
1748
}
1749

    
1750
target_ulong do_load_dbatl (CPUPPCState *env, int nr)
1751
{
1752
    return env->DBAT[1][nr];
1753
}
1754

    
1755
void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1756
{
1757
    target_ulong mask;
1758

    
1759
    dump_store_bat(env, 'D', 0, nr, value);
1760
    if (env->DBAT[0][nr] != value) {
1761
        /* When storing valid upper BAT, mask BEPI and BRPN
1762
         * and invalidate all TLBs covered by this BAT
1763
         */
1764
        mask = (value << 15) & 0x0FFE0000UL;
1765
#if !defined(FLUSH_ALL_TLBS)
1766
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1767
#endif
1768
        mask = (value << 15) & 0x0FFE0000UL;
1769
        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1770
            (value & ~0x0001FFFFUL & ~mask);
1771
        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1772
            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1773
#if !defined(FLUSH_ALL_TLBS)
1774
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1775
#else
1776
        tlb_flush(env, 1);
1777
#endif
1778
    }
1779
}
1780

    
1781
void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1782
{
1783
    dump_store_bat(env, 'D', 1, nr, value);
1784
    env->DBAT[1][nr] = value;
1785
}
1786

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

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

    
1893
/*****************************************************************************/
1894
/* Special registers manipulation */
1895
#if defined(TARGET_PPC64)
1896
target_ulong ppc_load_asr (CPUPPCState *env)
1897
{
1898
    return env->asr;
1899
}
1900

    
1901
void ppc_store_asr (CPUPPCState *env, target_ulong value)
1902
{
1903
    if (env->asr != value) {
1904
        env->asr = value;
1905
        tlb_flush(env, 1);
1906
    }
1907
}
1908
#endif
1909

    
1910
target_ulong do_load_sdr1 (CPUPPCState *env)
1911
{
1912
    return env->sdr1;
1913
}
1914

    
1915
void do_store_sdr1 (CPUPPCState *env, target_ulong value)
1916
{
1917
#if defined (DEBUG_MMU)
1918
    if (loglevel != 0) {
1919
        fprintf(logfile, "%s: 0x" ADDRX "\n", __func__, value);
1920
    }
1921
#endif
1922
    if (env->sdr1 != value) {
1923
        /* XXX: for PowerPC 64, should check that the HTABSIZE value
1924
         *      is <= 28
1925
         */
1926
        env->sdr1 = value;
1927
        tlb_flush(env, 1);
1928
    }
1929
}
1930

    
1931
#if 0 // Unused
1932
target_ulong do_load_sr (CPUPPCState *env, int srnum)
1933
{
1934
    return env->sr[srnum];
1935
}
1936
#endif
1937

    
1938
void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1939
{
1940
#if defined (DEBUG_MMU)
1941
    if (loglevel != 0) {
1942
        fprintf(logfile, "%s: reg=%d 0x" ADDRX " " ADDRX "\n",
1943
                __func__, srnum, value, env->sr[srnum]);
1944
    }
1945
#endif
1946
    if (env->sr[srnum] != value) {
1947
        env->sr[srnum] = value;
1948
#if !defined(FLUSH_ALL_TLBS) && 0
1949
        {
1950
            target_ulong page, end;
1951
            /* Invalidate 256 MB of virtual memory */
1952
            page = (16 << 20) * srnum;
1953
            end = page + (16 << 20);
1954
            for (; page != end; page += TARGET_PAGE_SIZE)
1955
                tlb_flush_page(env, page);
1956
        }
1957
#else
1958
        tlb_flush(env, 1);
1959
#endif
1960
    }
1961
}
1962
#endif /* !defined (CONFIG_USER_ONLY) */
1963

    
1964
target_ulong ppc_load_xer (CPUPPCState *env)
1965
{
1966
    return hreg_load_xer(env);
1967
}
1968

    
1969
void ppc_store_xer (CPUPPCState *env, target_ulong value)
1970
{
1971
    hreg_store_xer(env, value);
1972
}
1973

    
1974
/* GDBstub can read and write MSR... */
1975
void ppc_store_msr (CPUPPCState *env, target_ulong value)
1976
{
1977
    hreg_store_msr(env, value);
1978
}
1979

    
1980
/*****************************************************************************/
1981
/* Exception processing */
1982
#if defined (CONFIG_USER_ONLY)
1983
void do_interrupt (CPUState *env)
1984
{
1985
    env->exception_index = POWERPC_EXCP_NONE;
1986
    env->error_code = 0;
1987
}
1988

    
1989
void ppc_hw_interrupt (CPUState *env)
1990
{
1991
    env->exception_index = POWERPC_EXCP_NONE;
1992
    env->error_code = 0;
1993
}
1994
#else /* defined (CONFIG_USER_ONLY) */
1995
static always_inline void dump_syscall (CPUState *env)
1996
{
1997
    fprintf(logfile, "syscall r0=0x" REGX " r3=0x" REGX " r4=0x" REGX
1998
            " r5=0x" REGX " r6=0x" REGX " nip=0x" ADDRX "\n",
1999
            env->gpr[0], env->gpr[3], env->gpr[4],
2000
            env->gpr[5], env->gpr[6], env->nip);
2001
}
2002

    
2003
/* Note that this function should be greatly optimized
2004
 * when called with a constant excp, from ppc_hw_interrupt
2005
 */
2006
static always_inline void powerpc_excp (CPUState *env,
2007
                                        int excp_model, int excp)
2008
{
2009
    target_ulong msr, new_msr, vector;
2010
    int srr0, srr1, asrr0, asrr1;
2011
#if defined(TARGET_PPC64H)
2012
    int lpes0, lpes1, lev;
2013

    
2014
    lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2015
    lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2016
#endif
2017

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

    
2640
void do_interrupt (CPUState *env)
2641
{
2642
    powerpc_excp(env, env->excp_model, env->exception_index);
2643
}
2644

    
2645
void ppc_hw_interrupt (CPUPPCState *env)
2646
{
2647
#if defined(TARGET_PPC64H)
2648
    int hdice;
2649
#endif
2650

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

    
2782
void cpu_dump_EA (target_ulong EA)
2783
{
2784
    FILE *f;
2785

    
2786
    if (logfile) {
2787
        f = logfile;
2788
    } else {
2789
        f = stdout;
2790
        return;
2791
    }
2792
    fprintf(f, "Memory access at address " ADDRX "\n", EA);
2793
}
2794

    
2795
void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2796
{
2797
    FILE *f;
2798

    
2799
    if (logfile) {
2800
        f = logfile;
2801
    } else {
2802
        f = stdout;
2803
        return;
2804
    }
2805
    fprintf(f, "Return from exception at " ADDRX " with flags " ADDRX "\n",
2806
            RA, msr);
2807
}
2808

    
2809
void cpu_ppc_reset (void *opaque)
2810
{
2811
    CPUPPCState *env;
2812
    target_ulong msr;
2813

    
2814
    env = opaque;
2815
    msr = (target_ulong)0;
2816
#if defined(TARGET_PPC64)
2817
    msr |= (target_ulong)0 << MSR_HV; /* Should be 1... */
2818
#endif
2819
    msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
2820
    msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
2821
    msr |= (target_ulong)1 << MSR_EP;
2822
#if defined (DO_SINGLE_STEP) && 0
2823
    /* Single step trace mode */
2824
    msr |= (target_ulong)1 << MSR_SE;
2825
    msr |= (target_ulong)1 << MSR_BE;
2826
#endif
2827
#if defined(CONFIG_USER_ONLY)
2828
    msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
2829
    msr |= (target_ulong)1 << MSR_PR;
2830
#else
2831
    env->nip = env->hreset_vector | env->excp_prefix;
2832
    if (env->mmu_model != POWERPC_MMU_REAL_4xx)
2833
        ppc_tlb_invalidate_all(env);
2834
#endif
2835
    env->msr = msr;
2836
    hreg_compute_hflags(env);
2837
    env->reserve = -1;
2838
    /* Be sure no exception or interrupt is pending */
2839
    env->pending_interrupts = 0;
2840
    env->exception_index = POWERPC_EXCP_NONE;
2841
    env->error_code = 0;
2842
    /* Flush all TLBs */
2843
    tlb_flush(env, 1);
2844
}
2845

    
2846
CPUPPCState *cpu_ppc_init (void)
2847
{
2848
    CPUPPCState *env;
2849

    
2850
    env = qemu_mallocz(sizeof(CPUPPCState));
2851
    if (!env)
2852
        return NULL;
2853
    cpu_exec_init(env);
2854

    
2855
    return env;
2856
}
2857

    
2858
void cpu_ppc_close (CPUPPCState *env)
2859
{
2860
    /* Should also remove all opcode tables... */
2861
    free(env);
2862
}