Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ d4c430a8

History | View | Annotate | Download (93.6 kB)

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

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

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

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

    
48

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

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

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

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

    
73

    
74
/*****************************************************************************/
75
/* PowerPC MMU emulation */
76

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

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

    
97
    return 1;
98
}
99

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

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

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

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

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

    
131
static inline int pp_check(int key, int pp, int nx)
132
{
133
    int access;
134

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

    
168
    return access;
169
}
170

    
171
static inline int check_prot(int prot, int rw, int access_type)
172
{
173
    int ret;
174

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

    
192
    return ret;
193
}
194

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

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

    
254
    return ret;
255
}
256

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

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

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

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

    
293
    return store;
294
}
295

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

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

    
310
    return nr;
311
}
312

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

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

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

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

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

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

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

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

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

    
438
    return ret;
439
}
440

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

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

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

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

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

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

    
568
/* PTE table lookup */
569
static inline int _find_pte(mmu_ctx_t *ctx, int is_64b, int h, int rw,
570
                            int type, int target_page_bits)
571
{
572
    target_ulong base, pte0, pte1;
573
    int i, good = -1;
574
    int ret, r;
575

    
576
    ret = -1; /* No entry found */
577
    base = ctx->pg_addr[h];
578
    for (i = 0; i < 8; i++) {
579
#if defined(TARGET_PPC64)
580
        if (is_64b) {
581
            pte0 = ldq_phys(base + (i * 16));
582
            pte1 = ldq_phys(base + (i * 16) + 8);
583

    
584
            /* We have a TLB that saves 4K pages, so let's
585
             * split a huge page to 4k chunks */
586
            if (target_page_bits != TARGET_PAGE_BITS)
587
                pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1))
588
                        & TARGET_PAGE_MASK;
589

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

    
648
    return ret;
649
}
650

    
651
static inline int find_pte32(mmu_ctx_t *ctx, int h, int rw, int type,
652
                             int target_page_bits)
653
{
654
    return _find_pte(ctx, 0, h, rw, type, target_page_bits);
655
}
656

    
657
#if defined(TARGET_PPC64)
658
static inline int find_pte64(mmu_ctx_t *ctx, int h, int rw, int type,
659
                             int target_page_bits)
660
{
661
    return _find_pte(ctx, 1, h, rw, type, target_page_bits);
662
}
663
#endif
664

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

    
673
    return find_pte32(ctx, h, rw, type, target_page_bits);
674
}
675

    
676
#if defined(TARGET_PPC64)
677
static ppc_slb_t *slb_get_entry(CPUPPCState *env, int nr)
678
{
679
    ppc_slb_t *retval = &env->slb[nr];
680

    
681
#if 0 // XXX implement bridge mode?
682
    if (env->spr[SPR_ASR] & 1) {
683
        target_phys_addr_t sr_base;
684

685
        sr_base = env->spr[SPR_ASR] & 0xfffffffffffff000;
686
        sr_base += (12 * nr);
687

688
        retval->tmp64 = ldq_phys(sr_base);
689
        retval->tmp = ldl_phys(sr_base + 8);
690
    }
691
#endif
692

    
693
    return retval;
694
}
695

    
696
static void slb_set_entry(CPUPPCState *env, int nr, ppc_slb_t *slb)
697
{
698
    ppc_slb_t *entry = &env->slb[nr];
699

    
700
    if (slb == entry)
701
        return;
702

    
703
    entry->tmp64 = slb->tmp64;
704
    entry->tmp = slb->tmp;
705
}
706

    
707
static inline int slb_is_valid(ppc_slb_t *slb)
708
{
709
    return (int)(slb->tmp64 & 0x0000000008000000ULL);
710
}
711

    
712
static inline void slb_invalidate(ppc_slb_t *slb)
713
{
714
    slb->tmp64 &= ~0x0000000008000000ULL;
715
}
716

    
717
static inline int slb_lookup(CPUPPCState *env, target_ulong eaddr,
718
                             target_ulong *vsid, target_ulong *page_mask,
719
                             int *attr, int *target_page_bits)
720
{
721
    target_ulong mask;
722
    int n, ret;
723

    
724
    ret = -5;
725
    LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
726
    mask = 0x0000000000000000ULL; /* Avoid gcc warning */
727
    for (n = 0; n < env->slb_nr; n++) {
728
        ppc_slb_t *slb = slb_get_entry(env, n);
729

    
730
        LOG_SLB("%s: seg %d %016" PRIx64 " %08"
731
                    PRIx32 "\n", __func__, n, slb->tmp64, slb->tmp);
732
        if (slb_is_valid(slb)) {
733
            /* SLB entry is valid */
734
            mask = 0xFFFFFFFFF0000000ULL;
735
            if (slb->tmp & 0x8) {
736
                /* 16 MB PTEs */
737
                if (target_page_bits)
738
                    *target_page_bits = 24;
739
            } else {
740
                /* 4 KB PTEs */
741
                if (target_page_bits)
742
                    *target_page_bits = TARGET_PAGE_BITS;
743
            }
744
            if ((eaddr & mask) == (slb->tmp64 & mask)) {
745
                /* SLB match */
746
                *vsid = ((slb->tmp64 << 24) | (slb->tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
747
                *page_mask = ~mask;
748
                *attr = slb->tmp & 0xFF;
749
                ret = n;
750
                break;
751
            }
752
        }
753
    }
754

    
755
    return ret;
756
}
757

    
758
void ppc_slb_invalidate_all (CPUPPCState *env)
759
{
760
    int n, do_invalidate;
761

    
762
    do_invalidate = 0;
763
    /* XXX: Warning: slbia never invalidates the first segment */
764
    for (n = 1; n < env->slb_nr; n++) {
765
        ppc_slb_t *slb = slb_get_entry(env, n);
766

    
767
        if (slb_is_valid(slb)) {
768
            slb_invalidate(slb);
769
            slb_set_entry(env, n, slb);
770
            /* XXX: given the fact that segment size is 256 MB or 1TB,
771
             *      and we still don't have a tlb_flush_mask(env, n, mask)
772
             *      in Qemu, we just invalidate all TLBs
773
             */
774
            do_invalidate = 1;
775
        }
776
    }
777
    if (do_invalidate)
778
        tlb_flush(env, 1);
779
}
780

    
781
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
782
{
783
    target_ulong vsid, page_mask;
784
    int attr;
785
    int n;
786

    
787
    n = slb_lookup(env, T0, &vsid, &page_mask, &attr, NULL);
788
    if (n >= 0) {
789
        ppc_slb_t *slb = slb_get_entry(env, n);
790

    
791
        if (slb_is_valid(slb)) {
792
            slb_invalidate(slb);
793
            slb_set_entry(env, n, slb);
794
            /* XXX: given the fact that segment size is 256 MB or 1TB,
795
             *      and we still don't have a tlb_flush_mask(env, n, mask)
796
             *      in Qemu, we just invalidate all TLBs
797
             */
798
            tlb_flush(env, 1);
799
        }
800
    }
801
}
802

    
803
target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
804
{
805
    target_ulong rt;
806
    ppc_slb_t *slb = slb_get_entry(env, slb_nr);
807

    
808
    if (slb_is_valid(slb)) {
809
        /* SLB entry is valid */
810
        /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
811
        rt = slb->tmp >> 8;             /* 65:88 => 40:63 */
812
        rt |= (slb->tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
813
        /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
814
        rt |= ((slb->tmp >> 4) & 0xF) << 27;
815
    } else {
816
        rt = 0;
817
    }
818
    LOG_SLB("%s: %016" PRIx64 " %08" PRIx32 " => %d "
819
            TARGET_FMT_lx "\n", __func__, slb->tmp64, slb->tmp, slb_nr, rt);
820

    
821
    return rt;
822
}
823

    
824
void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
825
{
826
    ppc_slb_t *slb;
827

    
828
    uint64_t vsid;
829
    uint64_t esid;
830
    int flags, valid, slb_nr;
831

    
832
    vsid = rs >> 12;
833
    flags = ((rs >> 8) & 0xf);
834

    
835
    esid = rb >> 28;
836
    valid = (rb & (1 << 27));
837
    slb_nr = rb & 0xfff;
838

    
839
    slb = slb_get_entry(env, slb_nr);
840
    slb->tmp64 = (esid << 28) | valid | (vsid >> 24);
841
    slb->tmp = (vsid << 8) | (flags << 3);
842

    
843
    LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
844
            " %08" PRIx32 "\n", __func__, slb_nr, rb, rs, slb->tmp64,
845
            slb->tmp);
846

    
847
    slb_set_entry(env, slb_nr, slb);
848
}
849
#endif /* defined(TARGET_PPC64) */
850

    
851
/* Perform segment based translation */
852
static inline target_phys_addr_t get_pgaddr(target_phys_addr_t sdr1,
853
                                            int sdr_sh,
854
                                            target_phys_addr_t hash,
855
                                            target_phys_addr_t mask)
856
{
857
    return (sdr1 & ((target_phys_addr_t)(-1ULL) << sdr_sh)) | (hash & mask);
858
}
859

    
860
static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
861
                              target_ulong eaddr, int rw, int type)
862
{
863
    target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
864
    target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
865
#if defined(TARGET_PPC64)
866
    int attr;
867
#endif
868
    int ds, vsid_sh, sdr_sh, pr, target_page_bits;
869
    int ret, ret2;
870

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

    
1042
    return ret;
1043
}
1044

    
1045
/* Generic TLB check function for embedded PowerPC implementations */
1046
static inline int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
1047
                                   target_phys_addr_t *raddrp,
1048
                                   target_ulong address, uint32_t pid, int ext,
1049
                                   int i)
1050
{
1051
    target_ulong mask;
1052

    
1053
    /* Check valid flag */
1054
    if (!(tlb->prot & PAGE_VALID)) {
1055
        qemu_log("%s: TLB %d not valid\n", __func__, i);
1056
        return -1;
1057
    }
1058
    mask = ~(tlb->size - 1);
1059
    LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
1060
              " " TARGET_FMT_lx " %u\n", __func__, i, address, pid, tlb->EPN,
1061
              mask, (uint32_t)tlb->PID);
1062
    /* Check PID */
1063
    if (tlb->PID != 0 && tlb->PID != pid)
1064
        return -1;
1065
    /* Check effective address */
1066
    if ((address & mask) != tlb->EPN)
1067
        return -1;
1068
    *raddrp = (tlb->RPN & mask) | (address & ~mask);
1069
#if (TARGET_PHYS_ADDR_BITS >= 36)
1070
    if (ext) {
1071
        /* Extend the physical address to 36 bits */
1072
        *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1073
    }
1074
#endif
1075

    
1076
    return 0;
1077
}
1078

    
1079
/* Generic TLB search function for PowerPC embedded implementations */
1080
int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1081
{
1082
    ppcemb_tlb_t *tlb;
1083
    target_phys_addr_t raddr;
1084
    int i, ret;
1085

    
1086
    /* Default return value is no match */
1087
    ret = -1;
1088
    for (i = 0; i < env->nb_tlb; i++) {
1089
        tlb = &env->tlb[i].tlbe;
1090
        if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1091
            ret = i;
1092
            break;
1093
        }
1094
    }
1095

    
1096
    return ret;
1097
}
1098

    
1099
/* Helpers specific to PowerPC 40x implementations */
1100
static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
1101
{
1102
    ppcemb_tlb_t *tlb;
1103
    int i;
1104

    
1105
    for (i = 0; i < env->nb_tlb; i++) {
1106
        tlb = &env->tlb[i].tlbe;
1107
        tlb->prot &= ~PAGE_VALID;
1108
    }
1109
    tlb_flush(env, 1);
1110
}
1111

    
1112
static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
1113
                                              target_ulong eaddr, uint32_t pid)
1114
{
1115
#if !defined(FLUSH_ALL_TLBS)
1116
    ppcemb_tlb_t *tlb;
1117
    target_phys_addr_t raddr;
1118
    target_ulong page, end;
1119
    int i;
1120

    
1121
    for (i = 0; i < env->nb_tlb; i++) {
1122
        tlb = &env->tlb[i].tlbe;
1123
        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1124
            end = tlb->EPN + tlb->size;
1125
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1126
                tlb_flush_page(env, page);
1127
            tlb->prot &= ~PAGE_VALID;
1128
            break;
1129
        }
1130
    }
1131
#else
1132
    ppc4xx_tlb_invalidate_all(env);
1133
#endif
1134
}
1135

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

    
1143
    ret = -1;
1144
    raddr = (target_phys_addr_t)-1ULL;
1145
    pr = msr_pr;
1146
    for (i = 0; i < env->nb_tlb; i++) {
1147
        tlb = &env->tlb[i].tlbe;
1148
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1149
                             env->spr[SPR_40x_PID], 0, i) < 0)
1150
            continue;
1151
        zsel = (tlb->attr >> 4) & 0xF;
1152
        zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
1153
        LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1154
                    __func__, i, zsel, zpr, rw, tlb->attr);
1155
        /* Check execute enable bit */
1156
        switch (zpr) {
1157
        case 0x2:
1158
            if (pr != 0)
1159
                goto check_perms;
1160
            /* No break here */
1161
        case 0x3:
1162
            /* All accesses granted */
1163
            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1164
            ret = 0;
1165
            break;
1166
        case 0x0:
1167
            if (pr != 0) {
1168
                /* Raise Zone protection fault.  */
1169
                env->spr[SPR_40x_ESR] = 1 << 22;
1170
                ctx->prot = 0;
1171
                ret = -2;
1172
                break;
1173
            }
1174
            /* No break here */
1175
        case 0x1:
1176
        check_perms:
1177
            /* Check from TLB entry */
1178
            /* XXX: there is a problem here or in the TLB fill code... */
1179
            ctx->prot = tlb->prot;
1180
            ctx->prot |= PAGE_EXEC;
1181
            ret = check_prot(ctx->prot, rw, access_type);
1182
            if (ret == -2)
1183
                env->spr[SPR_40x_ESR] = 0;
1184
            break;
1185
        }
1186
        if (ret >= 0) {
1187
            ctx->raddr = raddr;
1188
            LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1189
                      " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1190
                      ret);
1191
            return 0;
1192
        }
1193
    }
1194
    LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1195
              " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1196

    
1197
    return ret;
1198
}
1199

    
1200
void store_40x_sler (CPUPPCState *env, uint32_t val)
1201
{
1202
    /* XXX: TO BE FIXED */
1203
    if (val != 0x00000000) {
1204
        cpu_abort(env, "Little-endian regions are not supported by now\n");
1205
    }
1206
    env->spr[SPR_405_SLER] = val;
1207
}
1208

    
1209
static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1210
                                          target_ulong address, int rw,
1211
                                          int access_type)
1212
{
1213
    ppcemb_tlb_t *tlb;
1214
    target_phys_addr_t raddr;
1215
    int i, prot, ret;
1216

    
1217
    ret = -1;
1218
    raddr = (target_phys_addr_t)-1ULL;
1219
    for (i = 0; i < env->nb_tlb; i++) {
1220
        tlb = &env->tlb[i].tlbe;
1221
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1222
                             env->spr[SPR_BOOKE_PID], 1, i) < 0)
1223
            continue;
1224
        if (msr_pr != 0)
1225
            prot = tlb->prot & 0xF;
1226
        else
1227
            prot = (tlb->prot >> 4) & 0xF;
1228
        /* Check the address space */
1229
        if (access_type == ACCESS_CODE) {
1230
            if (msr_ir != (tlb->attr & 1))
1231
                continue;
1232
            ctx->prot = prot;
1233
            if (prot & PAGE_EXEC) {
1234
                ret = 0;
1235
                break;
1236
            }
1237
            ret = -3;
1238
        } else {
1239
            if (msr_dr != (tlb->attr & 1))
1240
                continue;
1241
            ctx->prot = prot;
1242
            if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
1243
                ret = 0;
1244
                break;
1245
            }
1246
            ret = -2;
1247
        }
1248
    }
1249
    if (ret >= 0)
1250
        ctx->raddr = raddr;
1251

    
1252
    return ret;
1253
}
1254

    
1255
static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1256
                                 target_ulong eaddr, int rw)
1257
{
1258
    int in_plb, ret;
1259

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

    
1318
    return ret;
1319
}
1320

    
1321
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1322
                          int rw, int access_type)
1323
{
1324
    int ret;
1325

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

    
1382
    return ret;
1383
}
1384

    
1385
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1386
{
1387
    mmu_ctx_t ctx;
1388

    
1389
    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1390
        return -1;
1391

    
1392
    return ctx.raddr & TARGET_PAGE_MASK;
1393
}
1394

    
1395
/* Perform address translation */
1396
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1397
                              int mmu_idx, int is_softmmu)
1398
{
1399
    mmu_ctx_t ctx;
1400
    int access_type;
1401
    int ret = 0;
1402

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

    
1674
    base = BATu & ~0x0001FFFF;
1675
    end = base + mask + 0x00020000;
1676
    LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1677
             TARGET_FMT_lx ")\n", base, end, mask);
1678
    for (page = base; page != end; page += TARGET_PAGE_SIZE)
1679
        tlb_flush_page(env, page);
1680
    LOG_BATS("Flush done\n");
1681
}
1682
#endif
1683

    
1684
static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1685
                                  target_ulong value)
1686
{
1687
    LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1688
             nr, ul == 0 ? 'u' : 'l', value, env->nip);
1689
}
1690

    
1691
void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1692
{
1693
    target_ulong mask;
1694

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

    
1717
void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1718
{
1719
    dump_store_bat(env, 'I', 1, nr, value);
1720
    env->IBAT[1][nr] = value;
1721
}
1722

    
1723
void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1724
{
1725
    target_ulong mask;
1726

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

    
1749
void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1750
{
1751
    dump_store_bat(env, 'D', 1, nr, value);
1752
    env->DBAT[1][nr] = value;
1753
}
1754

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

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

    
1792
void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1793
{
1794
    target_ulong mask;
1795
    int do_inval;
1796

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

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

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

    
1944
/*****************************************************************************/
1945
/* Special registers manipulation */
1946
#if defined(TARGET_PPC64)
1947
void ppc_store_asr (CPUPPCState *env, target_ulong value)
1948
{
1949
    if (env->asr != value) {
1950
        env->asr = value;
1951
        tlb_flush(env, 1);
1952
    }
1953
}
1954
#endif
1955

    
1956
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
1957
{
1958
    LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
1959
    if (env->sdr1 != value) {
1960
        /* XXX: for PowerPC 64, should check that the HTABSIZE value
1961
         *      is <= 28
1962
         */
1963
        env->sdr1 = value;
1964
        tlb_flush(env, 1);
1965
    }
1966
}
1967

    
1968
#if defined(TARGET_PPC64)
1969
target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
1970
{
1971
    // XXX
1972
    return 0;
1973
}
1974
#endif
1975

    
1976
void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1977
{
1978
    LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
1979
            srnum, value, env->sr[srnum]);
1980
#if defined(TARGET_PPC64)
1981
    if (env->mmu_model & POWERPC_MMU_64) {
1982
        uint64_t rb = 0, rs = 0;
1983

    
1984
        /* ESID = srnum */
1985
        rb |= ((uint32_t)srnum & 0xf) << 28;
1986
        /* Set the valid bit */
1987
        rb |= 1 << 27;
1988
        /* Index = ESID */
1989
        rb |= (uint32_t)srnum;
1990

    
1991
        /* VSID = VSID */
1992
        rs |= (value & 0xfffffff) << 12;
1993
        /* flags = flags */
1994
        rs |= ((value >> 27) & 0xf) << 9;
1995

    
1996
        ppc_store_slb(env, rb, rs);
1997
    } else
1998
#endif
1999
    if (env->sr[srnum] != value) {
2000
        env->sr[srnum] = value;
2001
/* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2002
   flusing the whole TLB. */
2003
#if !defined(FLUSH_ALL_TLBS) && 0
2004
        {
2005
            target_ulong page, end;
2006
            /* Invalidate 256 MB of virtual memory */
2007
            page = (16 << 20) * srnum;
2008
            end = page + (16 << 20);
2009
            for (; page != end; page += TARGET_PAGE_SIZE)
2010
                tlb_flush_page(env, page);
2011
        }
2012
#else
2013
        tlb_flush(env, 1);
2014
#endif
2015
    }
2016
}
2017
#endif /* !defined (CONFIG_USER_ONLY) */
2018

    
2019
/* GDBstub can read and write MSR... */
2020
void ppc_store_msr (CPUPPCState *env, target_ulong value)
2021
{
2022
    hreg_store_msr(env, value, 0);
2023
}
2024

    
2025
/*****************************************************************************/
2026
/* Exception processing */
2027
#if defined (CONFIG_USER_ONLY)
2028
void do_interrupt (CPUState *env)
2029
{
2030
    env->exception_index = POWERPC_EXCP_NONE;
2031
    env->error_code = 0;
2032
}
2033

    
2034
void ppc_hw_interrupt (CPUState *env)
2035
{
2036
    env->exception_index = POWERPC_EXCP_NONE;
2037
    env->error_code = 0;
2038
}
2039
#else /* defined (CONFIG_USER_ONLY) */
2040
static inline void dump_syscall(CPUState *env)
2041
{
2042
    qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2043
                  " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2044
                  " nip=" TARGET_FMT_lx "\n",
2045
                  ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2046
                  ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2047
                  ppc_dump_gpr(env, 6), env->nip);
2048
}
2049

    
2050
/* Note that this function should be greatly optimized
2051
 * when called with a constant excp, from ppc_hw_interrupt
2052
 */
2053
static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2054
{
2055
    target_ulong msr, new_msr, vector;
2056
    int srr0, srr1, asrr0, asrr1;
2057
    int lpes0, lpes1, lev;
2058

    
2059
    if (0) {
2060
        /* XXX: find a suitable condition to enable the hypervisor mode */
2061
        lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2062
        lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2063
    } else {
2064
        /* Those values ensure we won't enter the hypervisor mode */
2065
        lpes0 = 0;
2066
        lpes1 = 1;
2067
    }
2068

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

    
2631
void do_interrupt (CPUState *env)
2632
{
2633
    powerpc_excp(env, env->excp_model, env->exception_index);
2634
}
2635

    
2636
void ppc_hw_interrupt (CPUPPCState *env)
2637
{
2638
    int hdice;
2639

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

    
2753
void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2754
{
2755
    qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
2756
             TARGET_FMT_lx "\n", RA, msr);
2757
}
2758

    
2759
void cpu_reset(CPUPPCState *env)
2760
{
2761
    target_ulong msr;
2762

    
2763
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
2764
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
2765
        log_cpu_state(env, 0);
2766
    }
2767

    
2768
    msr = (target_ulong)0;
2769
    if (0) {
2770
        /* XXX: find a suitable condition to enable the hypervisor mode */
2771
        msr |= (target_ulong)MSR_HVB;
2772
    }
2773
    msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
2774
    msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
2775
    msr |= (target_ulong)1 << MSR_EP;
2776
#if defined (DO_SINGLE_STEP) && 0
2777
    /* Single step trace mode */
2778
    msr |= (target_ulong)1 << MSR_SE;
2779
    msr |= (target_ulong)1 << MSR_BE;
2780
#endif
2781
#if defined(CONFIG_USER_ONLY)
2782
    msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
2783
    msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
2784
    msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
2785
    msr |= (target_ulong)1 << MSR_PR;
2786
#else
2787
    env->excp_prefix = env->hreset_excp_prefix;
2788
    env->nip = env->hreset_vector | env->excp_prefix;
2789
    if (env->mmu_model != POWERPC_MMU_REAL)
2790
        ppc_tlb_invalidate_all(env);
2791
#endif
2792
    env->msr = msr & env->msr_mask;
2793
#if defined(TARGET_PPC64)
2794
    if (env->mmu_model & POWERPC_MMU_64)
2795
        env->msr |= (1ULL << MSR_SF);
2796
#endif
2797
    hreg_compute_hflags(env);
2798
    env->reserve_addr = (target_ulong)-1ULL;
2799
    /* Be sure no exception or interrupt is pending */
2800
    env->pending_interrupts = 0;
2801
    env->exception_index = POWERPC_EXCP_NONE;
2802
    env->error_code = 0;
2803
    /* Flush all TLBs */
2804
    tlb_flush(env, 1);
2805
}
2806

    
2807
CPUPPCState *cpu_ppc_init (const char *cpu_model)
2808
{
2809
    CPUPPCState *env;
2810
    const ppc_def_t *def;
2811

    
2812
    def = cpu_ppc_find_by_name(cpu_model);
2813
    if (!def)
2814
        return NULL;
2815

    
2816
    env = qemu_mallocz(sizeof(CPUPPCState));
2817
    cpu_exec_init(env);
2818
    ppc_translate_init();
2819
    env->cpu_model_str = cpu_model;
2820
    cpu_ppc_register_internal(env, def);
2821

    
2822
    qemu_init_vcpu(env);
2823

    
2824
    return env;
2825
}
2826

    
2827
void cpu_ppc_close (CPUPPCState *env)
2828
{
2829
    /* Should also remove all opcode tables... */
2830
    qemu_free(env);
2831
}