~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to target-ppc/helper.c

  • Committer: bellard
  • Date: 2003-04-29 20:53:42 UTC
  • Revision ID: git-v1:43f04c233cb7d1731613bd6399c32ed09db01c16
alpha support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@110 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  PowerPC emulation helpers for qemu.
3
 
 *
4
 
 *  Copyright (c) 2003-2007 Jocelyn Mayer
5
 
 *
6
 
 * This library is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU Lesser General Public
8
 
 * License as published by the Free Software Foundation; either
9
 
 * version 2 of the License, or (at your option) any later version.
10
 
 *
11
 
 * This library is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
 * Lesser General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this library; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
 */
20
 
#include <stdarg.h>
21
 
#include <stdlib.h>
22
 
#include <stdio.h>
23
 
#include <string.h>
24
 
#include <inttypes.h>
25
 
#include <signal.h>
26
 
#include <assert.h>
27
 
 
28
 
#include "cpu.h"
29
 
#include "exec-all.h"
30
 
#include "helper_regs.h"
31
 
#include "qemu-common.h"
32
 
 
33
 
//#define DEBUG_MMU
34
 
//#define DEBUG_BATS
35
 
//#define DEBUG_SLB
36
 
//#define DEBUG_SOFTWARE_TLB
37
 
//#define DUMP_PAGE_TABLES
38
 
//#define DEBUG_EXCEPTIONS
39
 
//#define FLUSH_ALL_TLBS
40
 
 
41
 
/*****************************************************************************/
42
 
/* PowerPC MMU emulation */
43
 
 
44
 
#if defined(CONFIG_USER_ONLY)
45
 
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
46
 
                              int mmu_idx, int is_softmmu)
47
 
{
48
 
    int exception, error_code;
49
 
 
50
 
    if (rw == 2) {
51
 
        exception = POWERPC_EXCP_ISI;
52
 
        error_code = 0x40000000;
53
 
    } else {
54
 
        exception = POWERPC_EXCP_DSI;
55
 
        error_code = 0x40000000;
56
 
        if (rw)
57
 
            error_code |= 0x02000000;
58
 
        env->spr[SPR_DAR] = address;
59
 
        env->spr[SPR_DSISR] = error_code;
60
 
    }
61
 
    env->exception_index = exception;
62
 
    env->error_code = error_code;
63
 
 
64
 
    return 1;
65
 
}
66
 
 
67
 
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
68
 
{
69
 
    return addr;
70
 
}
71
 
 
72
 
#else
73
 
/* Common routines used by software and hardware TLBs emulation */
74
 
static always_inline int pte_is_valid (target_ulong pte0)
75
 
{
76
 
    return pte0 & 0x80000000 ? 1 : 0;
77
 
}
78
 
 
79
 
static always_inline void pte_invalidate (target_ulong *pte0)
80
 
{
81
 
    *pte0 &= ~0x80000000;
82
 
}
83
 
 
84
 
#if defined(TARGET_PPC64)
85
 
static always_inline int pte64_is_valid (target_ulong pte0)
86
 
{
87
 
    return pte0 & 0x0000000000000001ULL ? 1 : 0;
88
 
}
89
 
 
90
 
static always_inline void pte64_invalidate (target_ulong *pte0)
91
 
{
92
 
    *pte0 &= ~0x0000000000000001ULL;
93
 
}
94
 
#endif
95
 
 
96
 
#define PTE_PTEM_MASK 0x7FFFFFBF
97
 
#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
98
 
#if defined(TARGET_PPC64)
99
 
#define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
100
 
#define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
101
 
#endif
102
 
 
103
 
static always_inline int pp_check (int key, int pp, int nx)
104
 
{
105
 
    int access;
106
 
 
107
 
    /* Compute access rights */
108
 
    /* When pp is 3/7, the result is undefined. Set it to noaccess */
109
 
    access = 0;
110
 
    if (key == 0) {
111
 
        switch (pp) {
112
 
        case 0x0:
113
 
        case 0x1:
114
 
        case 0x2:
115
 
            access |= PAGE_WRITE;
116
 
            /* No break here */
117
 
        case 0x3:
118
 
        case 0x6:
119
 
            access |= PAGE_READ;
120
 
            break;
121
 
        }
122
 
    } else {
123
 
        switch (pp) {
124
 
        case 0x0:
125
 
        case 0x6:
126
 
            access = 0;
127
 
            break;
128
 
        case 0x1:
129
 
        case 0x3:
130
 
            access = PAGE_READ;
131
 
            break;
132
 
        case 0x2:
133
 
            access = PAGE_READ | PAGE_WRITE;
134
 
            break;
135
 
        }
136
 
    }
137
 
    if (nx == 0)
138
 
        access |= PAGE_EXEC;
139
 
 
140
 
    return access;
141
 
}
142
 
 
143
 
static always_inline int check_prot (int prot, int rw, int access_type)
144
 
{
145
 
    int ret;
146
 
 
147
 
    if (access_type == ACCESS_CODE) {
148
 
        if (prot & PAGE_EXEC)
149
 
            ret = 0;
150
 
        else
151
 
            ret = -2;
152
 
    } else if (rw) {
153
 
        if (prot & PAGE_WRITE)
154
 
            ret = 0;
155
 
        else
156
 
            ret = -2;
157
 
    } else {
158
 
        if (prot & PAGE_READ)
159
 
            ret = 0;
160
 
        else
161
 
            ret = -2;
162
 
    }
163
 
 
164
 
    return ret;
165
 
}
166
 
 
167
 
static always_inline int _pte_check (mmu_ctx_t *ctx, int is_64b,
168
 
                                     target_ulong pte0, target_ulong pte1,
169
 
                                     int h, int rw, int type)
170
 
{
171
 
    target_ulong ptem, mmask;
172
 
    int access, ret, pteh, ptev, pp;
173
 
 
174
 
    access = 0;
175
 
    ret = -1;
176
 
    /* Check validity and table match */
177
 
#if defined(TARGET_PPC64)
178
 
    if (is_64b) {
179
 
        ptev = pte64_is_valid(pte0);
180
 
        pteh = (pte0 >> 1) & 1;
181
 
    } else
182
 
#endif
183
 
    {
184
 
        ptev = pte_is_valid(pte0);
185
 
        pteh = (pte0 >> 6) & 1;
186
 
    }
187
 
    if (ptev && h == pteh) {
188
 
        /* Check vsid & api */
189
 
#if defined(TARGET_PPC64)
190
 
        if (is_64b) {
191
 
            ptem = pte0 & PTE64_PTEM_MASK;
192
 
            mmask = PTE64_CHECK_MASK;
193
 
            pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
194
 
            ctx->nx |= (pte1 >> 2) & 1; /* No execute bit */
195
 
            ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
196
 
        } else
197
 
#endif
198
 
        {
199
 
            ptem = pte0 & PTE_PTEM_MASK;
200
 
            mmask = PTE_CHECK_MASK;
201
 
            pp = pte1 & 0x00000003;
202
 
        }
203
 
        if (ptem == ctx->ptem) {
204
 
            if (ctx->raddr != (target_phys_addr_t)-1ULL) {
205
 
                /* all matches should have equal RPN, WIMG & PP */
206
 
                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
207
 
                    if (loglevel != 0)
208
 
                        fprintf(logfile, "Bad RPN/WIMG/PP\n");
209
 
                    return -3;
210
 
                }
211
 
            }
212
 
            /* Compute access rights */
213
 
            access = pp_check(ctx->key, pp, ctx->nx);
214
 
            /* Keep the matching PTE informations */
215
 
            ctx->raddr = pte1;
216
 
            ctx->prot = access;
217
 
            ret = check_prot(ctx->prot, rw, type);
218
 
            if (ret == 0) {
219
 
                /* Access granted */
220
 
#if defined (DEBUG_MMU)
221
 
                if (loglevel != 0)
222
 
                    fprintf(logfile, "PTE access granted !\n");
223
 
#endif
224
 
            } else {
225
 
                /* Access right violation */
226
 
#if defined (DEBUG_MMU)
227
 
                if (loglevel != 0)
228
 
                    fprintf(logfile, "PTE access rejected\n");
229
 
#endif
230
 
            }
231
 
        }
232
 
    }
233
 
 
234
 
    return ret;
235
 
}
236
 
 
237
 
static always_inline int pte32_check (mmu_ctx_t *ctx,
238
 
                                      target_ulong pte0, target_ulong pte1,
239
 
                                      int h, int rw, int type)
240
 
{
241
 
    return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
242
 
}
243
 
 
244
 
#if defined(TARGET_PPC64)
245
 
static always_inline int pte64_check (mmu_ctx_t *ctx,
246
 
                                      target_ulong pte0, target_ulong pte1,
247
 
                                      int h, int rw, int type)
248
 
{
249
 
    return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
250
 
}
251
 
#endif
252
 
 
253
 
static always_inline int pte_update_flags (mmu_ctx_t *ctx, target_ulong *pte1p,
254
 
                                           int ret, int rw)
255
 
{
256
 
    int store = 0;
257
 
 
258
 
    /* Update page flags */
259
 
    if (!(*pte1p & 0x00000100)) {
260
 
        /* Update accessed flag */
261
 
        *pte1p |= 0x00000100;
262
 
        store = 1;
263
 
    }
264
 
    if (!(*pte1p & 0x00000080)) {
265
 
        if (rw == 1 && ret == 0) {
266
 
            /* Update changed flag */
267
 
            *pte1p |= 0x00000080;
268
 
            store = 1;
269
 
        } else {
270
 
            /* Force page fault for first write access */
271
 
            ctx->prot &= ~PAGE_WRITE;
272
 
        }
273
 
    }
274
 
 
275
 
    return store;
276
 
}
277
 
 
278
 
/* Software driven TLB helpers */
279
 
static always_inline int ppc6xx_tlb_getnum (CPUState *env, target_ulong eaddr,
280
 
                                            int way, int is_code)
281
 
{
282
 
    int nr;
283
 
 
284
 
    /* Select TLB num in a way from address */
285
 
    nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
286
 
    /* Select TLB way */
287
 
    nr += env->tlb_per_way * way;
288
 
    /* 6xx have separate TLBs for instructions and data */
289
 
    if (is_code && env->id_tlbs == 1)
290
 
        nr += env->nb_tlb;
291
 
 
292
 
    return nr;
293
 
}
294
 
 
295
 
static always_inline void ppc6xx_tlb_invalidate_all (CPUState *env)
296
 
{
297
 
    ppc6xx_tlb_t *tlb;
298
 
    int nr, max;
299
 
 
300
 
#if defined (DEBUG_SOFTWARE_TLB) && 0
301
 
    if (loglevel != 0) {
302
 
        fprintf(logfile, "Invalidate all TLBs\n");
303
 
    }
304
 
#endif
305
 
    /* Invalidate all defined software TLB */
306
 
    max = env->nb_tlb;
307
 
    if (env->id_tlbs == 1)
308
 
        max *= 2;
309
 
    for (nr = 0; nr < max; nr++) {
310
 
        tlb = &env->tlb[nr].tlb6;
311
 
        pte_invalidate(&tlb->pte0);
312
 
    }
313
 
    tlb_flush(env, 1);
314
 
}
315
 
 
316
 
static always_inline void __ppc6xx_tlb_invalidate_virt (CPUState *env,
317
 
                                                        target_ulong eaddr,
318
 
                                                        int is_code,
319
 
                                                        int match_epn)
320
 
{
321
 
#if !defined(FLUSH_ALL_TLBS)
322
 
    ppc6xx_tlb_t *tlb;
323
 
    int way, nr;
324
 
 
325
 
    /* Invalidate ITLB + DTLB, all ways */
326
 
    for (way = 0; way < env->nb_ways; way++) {
327
 
        nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
328
 
        tlb = &env->tlb[nr].tlb6;
329
 
        if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
330
 
#if defined (DEBUG_SOFTWARE_TLB)
331
 
            if (loglevel != 0) {
332
 
                fprintf(logfile, "TLB invalidate %d/%d " ADDRX "\n",
333
 
                        nr, env->nb_tlb, eaddr);
334
 
            }
335
 
#endif
336
 
            pte_invalidate(&tlb->pte0);
337
 
            tlb_flush_page(env, tlb->EPN);
338
 
        }
339
 
    }
340
 
#else
341
 
    /* XXX: PowerPC specification say this is valid as well */
342
 
    ppc6xx_tlb_invalidate_all(env);
343
 
#endif
344
 
}
345
 
 
346
 
static always_inline void ppc6xx_tlb_invalidate_virt (CPUState *env,
347
 
                                                      target_ulong eaddr,
348
 
                                                      int is_code)
349
 
{
350
 
    __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
351
 
}
352
 
 
353
 
void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
354
 
                       target_ulong pte0, target_ulong pte1)
355
 
{
356
 
    ppc6xx_tlb_t *tlb;
357
 
    int nr;
358
 
 
359
 
    nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
360
 
    tlb = &env->tlb[nr].tlb6;
361
 
#if defined (DEBUG_SOFTWARE_TLB)
362
 
    if (loglevel != 0) {
363
 
        fprintf(logfile, "Set TLB %d/%d EPN " ADDRX " PTE0 " ADDRX
364
 
                " PTE1 " ADDRX "\n", nr, env->nb_tlb, EPN, pte0, pte1);
365
 
    }
366
 
#endif
367
 
    /* Invalidate any pending reference in Qemu for this virtual address */
368
 
    __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
369
 
    tlb->pte0 = pte0;
370
 
    tlb->pte1 = pte1;
371
 
    tlb->EPN = EPN;
372
 
    /* Store last way for LRU mechanism */
373
 
    env->last_way = way;
374
 
}
375
 
 
376
 
static always_inline int ppc6xx_tlb_check (CPUState *env, mmu_ctx_t *ctx,
377
 
                                           target_ulong eaddr, int rw,
378
 
                                           int access_type)
379
 
{
380
 
    ppc6xx_tlb_t *tlb;
381
 
    int nr, best, way;
382
 
    int ret;
383
 
 
384
 
    best = -1;
385
 
    ret = -1; /* No TLB found */
386
 
    for (way = 0; way < env->nb_ways; way++) {
387
 
        nr = ppc6xx_tlb_getnum(env, eaddr, way,
388
 
                               access_type == ACCESS_CODE ? 1 : 0);
389
 
        tlb = &env->tlb[nr].tlb6;
390
 
        /* This test "emulates" the PTE index match for hardware TLBs */
391
 
        if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
392
 
#if defined (DEBUG_SOFTWARE_TLB)
393
 
            if (loglevel != 0) {
394
 
                fprintf(logfile, "TLB %d/%d %s [" ADDRX " " ADDRX
395
 
                        "] <> " ADDRX "\n",
396
 
                        nr, env->nb_tlb,
397
 
                        pte_is_valid(tlb->pte0) ? "valid" : "inval",
398
 
                        tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
399
 
            }
400
 
#endif
401
 
            continue;
402
 
        }
403
 
#if defined (DEBUG_SOFTWARE_TLB)
404
 
        if (loglevel != 0) {
405
 
            fprintf(logfile, "TLB %d/%d %s " ADDRX " <> " ADDRX " " ADDRX
406
 
                    " %c %c\n",
407
 
                    nr, env->nb_tlb,
408
 
                    pte_is_valid(tlb->pte0) ? "valid" : "inval",
409
 
                    tlb->EPN, eaddr, tlb->pte1,
410
 
                    rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
411
 
        }
412
 
#endif
413
 
        switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
414
 
        case -3:
415
 
            /* TLB inconsistency */
416
 
            return -1;
417
 
        case -2:
418
 
            /* Access violation */
419
 
            ret = -2;
420
 
            best = nr;
421
 
            break;
422
 
        case -1:
423
 
        default:
424
 
            /* No match */
425
 
            break;
426
 
        case 0:
427
 
            /* access granted */
428
 
            /* XXX: we should go on looping to check all TLBs consistency
429
 
             *      but we can speed-up the whole thing as the
430
 
             *      result would be undefined if TLBs are not consistent.
431
 
             */
432
 
            ret = 0;
433
 
            best = nr;
434
 
            goto done;
435
 
        }
436
 
    }
437
 
    if (best != -1) {
438
 
    done:
439
 
#if defined (DEBUG_SOFTWARE_TLB)
440
 
        if (loglevel != 0) {
441
 
            fprintf(logfile, "found TLB at addr " PADDRX " prot=%01x ret=%d\n",
442
 
                    ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
443
 
        }
444
 
#endif
445
 
        /* Update page flags */
446
 
        pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
447
 
    }
448
 
 
449
 
    return ret;
450
 
}
451
 
 
452
 
/* Perform BAT hit & translation */
453
 
static always_inline void bat_size_prot (CPUState *env, target_ulong *blp,
454
 
                                         int *validp, int *protp,
455
 
                                         target_ulong *BATu, target_ulong *BATl)
456
 
{
457
 
    target_ulong bl;
458
 
    int pp, valid, prot;
459
 
 
460
 
    bl = (*BATu & 0x00001FFC) << 15;
461
 
    valid = 0;
462
 
    prot = 0;
463
 
    if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
464
 
        ((msr_pr != 0) && (*BATu & 0x00000001))) {
465
 
        valid = 1;
466
 
        pp = *BATl & 0x00000003;
467
 
        if (pp != 0) {
468
 
            prot = PAGE_READ | PAGE_EXEC;
469
 
            if (pp == 0x2)
470
 
                prot |= PAGE_WRITE;
471
 
        }
472
 
    }
473
 
    *blp = bl;
474
 
    *validp = valid;
475
 
    *protp = prot;
476
 
}
477
 
 
478
 
static always_inline void bat_601_size_prot (CPUState *env,target_ulong *blp,
479
 
                                             int *validp, int *protp,
480
 
                                             target_ulong *BATu,
481
 
                                             target_ulong *BATl)
482
 
{
483
 
    target_ulong bl;
484
 
    int key, pp, valid, prot;
485
 
 
486
 
    bl = (*BATl & 0x0000003F) << 17;
487
 
#if defined (DEBUG_BATS)
488
 
    if (loglevel != 0) {
489
 
        fprintf(logfile, "b %02x ==> bl " ADDRX " msk " ADDRX "\n",
490
 
                (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
491
 
    }
492
 
#endif
493
 
    prot = 0;
494
 
    valid = (*BATl >> 6) & 1;
495
 
    if (valid) {
496
 
        pp = *BATu & 0x00000003;
497
 
        if (msr_pr == 0)
498
 
            key = (*BATu >> 3) & 1;
499
 
        else
500
 
            key = (*BATu >> 2) & 1;
501
 
        prot = pp_check(key, pp, 0);
502
 
    }
503
 
    *blp = bl;
504
 
    *validp = valid;
505
 
    *protp = prot;
506
 
}
507
 
 
508
 
static always_inline int get_bat (CPUState *env, mmu_ctx_t *ctx,
509
 
                                  target_ulong virtual, int rw, int type)
510
 
{
511
 
    target_ulong *BATlt, *BATut, *BATu, *BATl;
512
 
    target_ulong base, BEPIl, BEPIu, bl;
513
 
    int i, valid, prot;
514
 
    int ret = -1;
515
 
 
516
 
#if defined (DEBUG_BATS)
517
 
    if (loglevel != 0) {
518
 
        fprintf(logfile, "%s: %cBAT v " ADDRX "\n", __func__,
519
 
                type == ACCESS_CODE ? 'I' : 'D', virtual);
520
 
    }
521
 
#endif
522
 
    switch (type) {
523
 
    case ACCESS_CODE:
524
 
        BATlt = env->IBAT[1];
525
 
        BATut = env->IBAT[0];
526
 
        break;
527
 
    default:
528
 
        BATlt = env->DBAT[1];
529
 
        BATut = env->DBAT[0];
530
 
        break;
531
 
    }
532
 
    base = virtual & 0xFFFC0000;
533
 
    for (i = 0; i < env->nb_BATs; i++) {
534
 
        BATu = &BATut[i];
535
 
        BATl = &BATlt[i];
536
 
        BEPIu = *BATu & 0xF0000000;
537
 
        BEPIl = *BATu & 0x0FFE0000;
538
 
        if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
539
 
            bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
540
 
        } else {
541
 
            bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
542
 
        }
543
 
#if defined (DEBUG_BATS)
544
 
        if (loglevel != 0) {
545
 
            fprintf(logfile, "%s: %cBAT%d v " ADDRX " BATu " ADDRX
546
 
                    " BATl " ADDRX "\n", __func__,
547
 
                    type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
548
 
        }
549
 
#endif
550
 
        if ((virtual & 0xF0000000) == BEPIu &&
551
 
            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
552
 
            /* BAT matches */
553
 
            if (valid != 0) {
554
 
                /* Get physical address */
555
 
                ctx->raddr = (*BATl & 0xF0000000) |
556
 
                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
557
 
                    (virtual & 0x0001F000);
558
 
                /* Compute access rights */
559
 
                ctx->prot = prot;
560
 
                ret = check_prot(ctx->prot, rw, type);
561
 
#if defined (DEBUG_BATS)
562
 
                if (ret == 0 && loglevel != 0) {
563
 
                    fprintf(logfile, "BAT %d match: r " PADDRX " prot=%c%c\n",
564
 
                            i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
565
 
                            ctx->prot & PAGE_WRITE ? 'W' : '-');
566
 
                }
567
 
#endif
568
 
                break;
569
 
            }
570
 
        }
571
 
    }
572
 
    if (ret < 0) {
573
 
#if defined (DEBUG_BATS)
574
 
        if (loglevel != 0) {
575
 
            fprintf(logfile, "no BAT match for " ADDRX ":\n", virtual);
576
 
            for (i = 0; i < 4; i++) {
577
 
                BATu = &BATut[i];
578
 
                BATl = &BATlt[i];
579
 
                BEPIu = *BATu & 0xF0000000;
580
 
                BEPIl = *BATu & 0x0FFE0000;
581
 
                bl = (*BATu & 0x00001FFC) << 15;
582
 
                fprintf(logfile, "%s: %cBAT%d v " ADDRX " BATu " ADDRX
583
 
                        " BATl " ADDRX " \n\t" ADDRX " " ADDRX " " ADDRX "\n",
584
 
                        __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
585
 
                        *BATu, *BATl, BEPIu, BEPIl, bl);
586
 
            }
587
 
        }
588
 
#endif
589
 
    }
590
 
 
591
 
    /* No hit */
592
 
    return ret;
593
 
}
594
 
 
595
 
/* PTE table lookup */
596
 
static always_inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h,
597
 
                                    int rw, int type)
598
 
{
599
 
    target_ulong base, pte0, pte1;
600
 
    int i, good = -1;
601
 
    int ret, r;
602
 
 
603
 
    ret = -1; /* No entry found */
604
 
    base = ctx->pg_addr[h];
605
 
    for (i = 0; i < 8; i++) {
606
 
#if defined(TARGET_PPC64)
607
 
        if (is_64b) {
608
 
            pte0 = ldq_phys(base + (i * 16));
609
 
            pte1 =  ldq_phys(base + (i * 16) + 8);
610
 
            r = pte64_check(ctx, pte0, pte1, h, rw, type);
611
 
#if defined (DEBUG_MMU)
612
 
            if (loglevel != 0) {
613
 
                fprintf(logfile, "Load pte from " ADDRX " => " ADDRX " " ADDRX
614
 
                        " %d %d %d " ADDRX "\n",
615
 
                        base + (i * 16), pte0, pte1,
616
 
                        (int)(pte0 & 1), h, (int)((pte0 >> 1) & 1),
617
 
                        ctx->ptem);
618
 
            }
619
 
#endif
620
 
        } else
621
 
#endif
622
 
        {
623
 
            pte0 = ldl_phys(base + (i * 8));
624
 
            pte1 =  ldl_phys(base + (i * 8) + 4);
625
 
            r = pte32_check(ctx, pte0, pte1, h, rw, type);
626
 
#if defined (DEBUG_MMU)
627
 
            if (loglevel != 0) {
628
 
                fprintf(logfile, "Load pte from " ADDRX " => " ADDRX " " ADDRX
629
 
                        " %d %d %d " ADDRX "\n",
630
 
                        base + (i * 8), pte0, pte1,
631
 
                        (int)(pte0 >> 31), h, (int)((pte0 >> 6) & 1),
632
 
                        ctx->ptem);
633
 
            }
634
 
#endif
635
 
        }
636
 
        switch (r) {
637
 
        case -3:
638
 
            /* PTE inconsistency */
639
 
            return -1;
640
 
        case -2:
641
 
            /* Access violation */
642
 
            ret = -2;
643
 
            good = i;
644
 
            break;
645
 
        case -1:
646
 
        default:
647
 
            /* No PTE match */
648
 
            break;
649
 
        case 0:
650
 
            /* access granted */
651
 
            /* XXX: we should go on looping to check all PTEs consistency
652
 
             *      but if we can speed-up the whole thing as the
653
 
             *      result would be undefined if PTEs are not consistent.
654
 
             */
655
 
            ret = 0;
656
 
            good = i;
657
 
            goto done;
658
 
        }
659
 
    }
660
 
    if (good != -1) {
661
 
    done:
662
 
#if defined (DEBUG_MMU)
663
 
        if (loglevel != 0) {
664
 
            fprintf(logfile, "found PTE at addr " PADDRX " prot=%01x ret=%d\n",
665
 
                    ctx->raddr, ctx->prot, ret);
666
 
        }
667
 
#endif
668
 
        /* Update page flags */
669
 
        pte1 = ctx->raddr;
670
 
        if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
671
 
#if defined(TARGET_PPC64)
672
 
            if (is_64b) {
673
 
                stq_phys_notdirty(base + (good * 16) + 8, pte1);
674
 
            } else
675
 
#endif
676
 
            {
677
 
                stl_phys_notdirty(base + (good * 8) + 4, pte1);
678
 
            }
679
 
        }
680
 
    }
681
 
 
682
 
    return ret;
683
 
}
684
 
 
685
 
static always_inline int find_pte32 (mmu_ctx_t *ctx, int h, int rw, int type)
686
 
{
687
 
    return _find_pte(ctx, 0, h, rw, type);
688
 
}
689
 
 
690
 
#if defined(TARGET_PPC64)
691
 
static always_inline int find_pte64 (mmu_ctx_t *ctx, int h, int rw, int type)
692
 
{
693
 
    return _find_pte(ctx, 1, h, rw, type);
694
 
}
695
 
#endif
696
 
 
697
 
static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx,
698
 
                                   int h, int rw, int type)
699
 
{
700
 
#if defined(TARGET_PPC64)
701
 
    if (env->mmu_model & POWERPC_MMU_64)
702
 
        return find_pte64(ctx, h, rw, type);
703
 
#endif
704
 
 
705
 
    return find_pte32(ctx, h, rw, type);
706
 
}
707
 
 
708
 
#if defined(TARGET_PPC64)
709
 
static always_inline int slb_is_valid (uint64_t slb64)
710
 
{
711
 
    return slb64 & 0x0000000008000000ULL ? 1 : 0;
712
 
}
713
 
 
714
 
static always_inline void slb_invalidate (uint64_t *slb64)
715
 
{
716
 
    *slb64 &= ~0x0000000008000000ULL;
717
 
}
718
 
 
719
 
static always_inline int slb_lookup (CPUPPCState *env, target_ulong eaddr,
720
 
                                     target_ulong *vsid,
721
 
                                     target_ulong *page_mask, int *attr)
722
 
{
723
 
    target_phys_addr_t sr_base;
724
 
    target_ulong mask;
725
 
    uint64_t tmp64;
726
 
    uint32_t tmp;
727
 
    int n, ret;
728
 
 
729
 
    ret = -5;
730
 
    sr_base = env->spr[SPR_ASR];
731
 
#if defined(DEBUG_SLB)
732
 
    if (loglevel != 0) {
733
 
        fprintf(logfile, "%s: eaddr " ADDRX " base " PADDRX "\n",
734
 
                __func__, eaddr, sr_base);
735
 
    }
736
 
#endif
737
 
    mask = 0x0000000000000000ULL; /* Avoid gcc warning */
738
 
    for (n = 0; n < env->slb_nr; n++) {
739
 
        tmp64 = ldq_phys(sr_base);
740
 
        tmp = ldl_phys(sr_base + 8);
741
 
#if defined(DEBUG_SLB)
742
 
        if (loglevel != 0) {
743
 
            fprintf(logfile, "%s: seg %d " PADDRX " %016" PRIx64 " %08"
744
 
                    PRIx32 "\n", __func__, n, sr_base, tmp64, tmp);
745
 
        }
746
 
#endif
747
 
        if (slb_is_valid(tmp64)) {
748
 
            /* SLB entry is valid */
749
 
            switch (tmp64 & 0x0000000006000000ULL) {
750
 
            case 0x0000000000000000ULL:
751
 
                /* 256 MB segment */
752
 
                mask = 0xFFFFFFFFF0000000ULL;
753
 
                break;
754
 
            case 0x0000000002000000ULL:
755
 
                /* 1 TB segment */
756
 
                mask = 0xFFFF000000000000ULL;
757
 
                break;
758
 
            case 0x0000000004000000ULL:
759
 
            case 0x0000000006000000ULL:
760
 
                /* Reserved => segment is invalid */
761
 
                continue;
762
 
            }
763
 
            if ((eaddr & mask) == (tmp64 & mask)) {
764
 
                /* SLB match */
765
 
                *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
766
 
                *page_mask = ~mask;
767
 
                *attr = tmp & 0xFF;
768
 
                ret = n;
769
 
                break;
770
 
            }
771
 
        }
772
 
        sr_base += 12;
773
 
    }
774
 
 
775
 
    return ret;
776
 
}
777
 
 
778
 
void ppc_slb_invalidate_all (CPUPPCState *env)
779
 
{
780
 
    target_phys_addr_t sr_base;
781
 
    uint64_t tmp64;
782
 
    int n, do_invalidate;
783
 
 
784
 
    do_invalidate = 0;
785
 
    sr_base = env->spr[SPR_ASR];
786
 
    /* XXX: Warning: slbia never invalidates the first segment */
787
 
    for (n = 1; n < env->slb_nr; n++) {
788
 
        tmp64 = ldq_phys(sr_base);
789
 
        if (slb_is_valid(tmp64)) {
790
 
            slb_invalidate(&tmp64);
791
 
            stq_phys(sr_base, tmp64);
792
 
            /* XXX: given the fact that segment size is 256 MB or 1TB,
793
 
             *      and we still don't have a tlb_flush_mask(env, n, mask)
794
 
             *      in Qemu, we just invalidate all TLBs
795
 
             */
796
 
            do_invalidate = 1;
797
 
        }
798
 
        sr_base += 12;
799
 
    }
800
 
    if (do_invalidate)
801
 
        tlb_flush(env, 1);
802
 
}
803
 
 
804
 
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
805
 
{
806
 
    target_phys_addr_t sr_base;
807
 
    target_ulong vsid, page_mask;
808
 
    uint64_t tmp64;
809
 
    int attr;
810
 
    int n;
811
 
 
812
 
    n = slb_lookup(env, T0, &vsid, &page_mask, &attr);
813
 
    if (n >= 0) {
814
 
        sr_base = env->spr[SPR_ASR];
815
 
        sr_base += 12 * n;
816
 
        tmp64 = ldq_phys(sr_base);
817
 
        if (slb_is_valid(tmp64)) {
818
 
            slb_invalidate(&tmp64);
819
 
            stq_phys(sr_base, tmp64);
820
 
            /* XXX: given the fact that segment size is 256 MB or 1TB,
821
 
             *      and we still don't have a tlb_flush_mask(env, n, mask)
822
 
             *      in Qemu, we just invalidate all TLBs
823
 
             */
824
 
            tlb_flush(env, 1);
825
 
        }
826
 
    }
827
 
}
828
 
 
829
 
target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
830
 
{
831
 
    target_phys_addr_t sr_base;
832
 
    target_ulong rt;
833
 
    uint64_t tmp64;
834
 
    uint32_t tmp;
835
 
 
836
 
    sr_base = env->spr[SPR_ASR];
837
 
    sr_base += 12 * slb_nr;
838
 
    tmp64 = ldq_phys(sr_base);
839
 
    tmp = ldl_phys(sr_base + 8);
840
 
    if (tmp64 & 0x0000000008000000ULL) {
841
 
        /* SLB entry is valid */
842
 
        /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
843
 
        rt = tmp >> 8;             /* 65:88 => 40:63 */
844
 
        rt |= (tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
845
 
        /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
846
 
        rt |= ((tmp >> 4) & 0xF) << 27;
847
 
    } else {
848
 
        rt = 0;
849
 
    }
850
 
#if defined(DEBUG_SLB)
851
 
    if (loglevel != 0) {
852
 
        fprintf(logfile, "%s: " PADDRX " %016" PRIx64 " %08" PRIx32 " => %d "
853
 
                ADDRX "\n", __func__, sr_base, tmp64, tmp, slb_nr, rt);
854
 
    }
855
 
#endif
856
 
 
857
 
    return rt;
858
 
}
859
 
 
860
 
void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs)
861
 
{
862
 
    target_phys_addr_t sr_base;
863
 
    uint64_t tmp64;
864
 
    uint32_t tmp;
865
 
 
866
 
    sr_base = env->spr[SPR_ASR];
867
 
    sr_base += 12 * slb_nr;
868
 
    /* Copy Rs bits 37:63 to SLB 62:88 */
869
 
    tmp = rs << 8;
870
 
    tmp64 = (rs >> 24) & 0x7;
871
 
    /* Copy Rs bits 33:36 to SLB 89:92 */
872
 
    tmp |= ((rs >> 27) & 0xF) << 4;
873
 
    /* Set the valid bit */
874
 
    tmp64 |= 1 << 27;
875
 
    /* Set ESID */
876
 
    tmp64 |= (uint32_t)slb_nr << 28;
877
 
#if defined(DEBUG_SLB)
878
 
    if (loglevel != 0) {
879
 
        fprintf(logfile, "%s: %d " ADDRX " => " PADDRX " %016" PRIx64
880
 
                " %08" PRIx32 "\n", __func__,
881
 
                slb_nr, rs, sr_base, tmp64, tmp);
882
 
    }
883
 
#endif
884
 
    /* Write SLB entry to memory */
885
 
    stq_phys(sr_base, tmp64);
886
 
    stl_phys(sr_base + 8, tmp);
887
 
}
888
 
#endif /* defined(TARGET_PPC64) */
889
 
 
890
 
/* Perform segment based translation */
891
 
static always_inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
892
 
                                                    int sdr_sh,
893
 
                                                    target_phys_addr_t hash,
894
 
                                                    target_phys_addr_t mask)
895
 
{
896
 
    return (sdr1 & ((target_phys_addr_t)(-1ULL) << sdr_sh)) | (hash & mask);
897
 
}
898
 
 
899
 
static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
900
 
                                      target_ulong eaddr, int rw, int type)
901
 
{
902
 
    target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
903
 
    target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
904
 
#if defined(TARGET_PPC64)
905
 
    int attr;
906
 
#endif
907
 
    int ds, vsid_sh, sdr_sh, pr;
908
 
    int ret, ret2;
909
 
 
910
 
    pr = msr_pr;
911
 
#if defined(TARGET_PPC64)
912
 
    if (env->mmu_model & POWERPC_MMU_64) {
913
 
#if defined (DEBUG_MMU)
914
 
        if (loglevel != 0) {
915
 
            fprintf(logfile, "Check SLBs\n");
916
 
        }
917
 
#endif
918
 
        ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr);
919
 
        if (ret < 0)
920
 
            return ret;
921
 
        ctx->key = ((attr & 0x40) && (pr != 0)) ||
922
 
            ((attr & 0x80) && (pr == 0)) ? 1 : 0;
923
 
        ds = 0;
924
 
        ctx->nx = attr & 0x20 ? 1 : 0;
925
 
        vsid_mask = 0x00003FFFFFFFFF80ULL;
926
 
        vsid_sh = 7;
927
 
        sdr_sh = 18;
928
 
        sdr_mask = 0x3FF80;
929
 
    } else
930
 
#endif /* defined(TARGET_PPC64) */
931
 
    {
932
 
        sr = env->sr[eaddr >> 28];
933
 
        page_mask = 0x0FFFFFFF;
934
 
        ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
935
 
                    ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
936
 
        ds = sr & 0x80000000 ? 1 : 0;
937
 
        ctx->nx = sr & 0x10000000 ? 1 : 0;
938
 
        vsid = sr & 0x00FFFFFF;
939
 
        vsid_mask = 0x01FFFFC0;
940
 
        vsid_sh = 6;
941
 
        sdr_sh = 16;
942
 
        sdr_mask = 0xFFC0;
943
 
#if defined (DEBUG_MMU)
944
 
        if (loglevel != 0) {
945
 
            fprintf(logfile, "Check segment v=" ADDRX " %d " ADDRX
946
 
                    " nip=" ADDRX " lr=" ADDRX " ir=%d dr=%d pr=%d %d t=%d\n",
947
 
                    eaddr, (int)(eaddr >> 28), sr, env->nip,
948
 
                    env->lr, (int)msr_ir, (int)msr_dr, pr != 0 ? 1 : 0,
949
 
                    rw, type);
950
 
        }
951
 
#endif
952
 
    }
953
 
#if defined (DEBUG_MMU)
954
 
    if (loglevel != 0) {
955
 
        fprintf(logfile, "pte segment: key=%d ds %d nx %d vsid " ADDRX "\n",
956
 
                ctx->key, ds, ctx->nx, vsid);
957
 
    }
958
 
#endif
959
 
    ret = -1;
960
 
    if (!ds) {
961
 
        /* Check if instruction fetch is allowed, if needed */
962
 
        if (type != ACCESS_CODE || ctx->nx == 0) {
963
 
            /* Page address translation */
964
 
            /* Primary table address */
965
 
            sdr = env->sdr1;
966
 
            pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS;
967
 
#if defined(TARGET_PPC64)
968
 
            if (env->mmu_model & POWERPC_MMU_64) {
969
 
                htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
970
 
                /* XXX: this is false for 1 TB segments */
971
 
                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
972
 
            } else
973
 
#endif
974
 
            {
975
 
                htab_mask = sdr & 0x000001FF;
976
 
                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
977
 
            }
978
 
            mask = (htab_mask << sdr_sh) | sdr_mask;
979
 
#if defined (DEBUG_MMU)
980
 
            if (loglevel != 0) {
981
 
                fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX
982
 
                        " mask " PADDRX " " ADDRX "\n",
983
 
                        sdr, sdr_sh, hash, mask, page_mask);
984
 
            }
985
 
#endif
986
 
            ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask);
987
 
            /* Secondary table address */
988
 
            hash = (~hash) & vsid_mask;
989
 
#if defined (DEBUG_MMU)
990
 
            if (loglevel != 0) {
991
 
                fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX
992
 
                        " mask " PADDRX "\n",
993
 
                        sdr, sdr_sh, hash, mask);
994
 
            }
995
 
#endif
996
 
            ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
997
 
#if defined(TARGET_PPC64)
998
 
            if (env->mmu_model & POWERPC_MMU_64) {
999
 
                /* Only 5 bits of the page index are used in the AVPN */
1000
 
                ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
1001
 
            } else
1002
 
#endif
1003
 
            {
1004
 
                ctx->ptem = (vsid << 7) | (pgidx >> 10);
1005
 
            }
1006
 
            /* Initialize real address with an invalid value */
1007
 
            ctx->raddr = (target_phys_addr_t)-1ULL;
1008
 
            if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
1009
 
                         env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
1010
 
                /* Software TLB search */
1011
 
                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
1012
 
            } else {
1013
 
#if defined (DEBUG_MMU)
1014
 
                if (loglevel != 0) {
1015
 
                    fprintf(logfile, "0 sdr1=" PADDRX " vsid=" ADDRX " "
1016
 
                            "api=" ADDRX " hash=" PADDRX
1017
 
                            " pg_addr=" PADDRX "\n",
1018
 
                            sdr, vsid, pgidx, hash, ctx->pg_addr[0]);
1019
 
                }
1020
 
#endif
1021
 
                /* Primary table lookup */
1022
 
                ret = find_pte(env, ctx, 0, rw, type);
1023
 
                if (ret < 0) {
1024
 
                    /* Secondary table lookup */
1025
 
#if defined (DEBUG_MMU)
1026
 
                    if (eaddr != 0xEFFFFFFF && loglevel != 0) {
1027
 
                        fprintf(logfile, "1 sdr1=" PADDRX " vsid=" ADDRX " "
1028
 
                                "api=" ADDRX " hash=" PADDRX
1029
 
                                " pg_addr=" PADDRX "\n",
1030
 
                                sdr, vsid, pgidx, hash, ctx->pg_addr[1]);
1031
 
                    }
1032
 
#endif
1033
 
                    ret2 = find_pte(env, ctx, 1, rw, type);
1034
 
                    if (ret2 != -1)
1035
 
                        ret = ret2;
1036
 
                }
1037
 
            }
1038
 
#if defined (DUMP_PAGE_TABLES)
1039
 
            if (loglevel != 0) {
1040
 
                target_phys_addr_t curaddr;
1041
 
                uint32_t a0, a1, a2, a3;
1042
 
                fprintf(logfile, "Page table: " PADDRX " len " PADDRX "\n",
1043
 
                        sdr, mask + 0x80);
1044
 
                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
1045
 
                     curaddr += 16) {
1046
 
                    a0 = ldl_phys(curaddr);
1047
 
                    a1 = ldl_phys(curaddr + 4);
1048
 
                    a2 = ldl_phys(curaddr + 8);
1049
 
                    a3 = ldl_phys(curaddr + 12);
1050
 
                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
1051
 
                        fprintf(logfile, PADDRX ": %08x %08x %08x %08x\n",
1052
 
                                curaddr, a0, a1, a2, a3);
1053
 
                    }
1054
 
                }
1055
 
            }
1056
 
#endif
1057
 
        } else {
1058
 
#if defined (DEBUG_MMU)
1059
 
            if (loglevel != 0)
1060
 
                fprintf(logfile, "No access allowed\n");
1061
 
#endif
1062
 
            ret = -3;
1063
 
        }
1064
 
    } else {
1065
 
#if defined (DEBUG_MMU)
1066
 
        if (loglevel != 0)
1067
 
            fprintf(logfile, "direct store...\n");
1068
 
#endif
1069
 
        /* Direct-store segment : absolutely *BUGGY* for now */
1070
 
        switch (type) {
1071
 
        case ACCESS_INT:
1072
 
            /* Integer load/store : only access allowed */
1073
 
            break;
1074
 
        case ACCESS_CODE:
1075
 
            /* No code fetch is allowed in direct-store areas */
1076
 
            return -4;
1077
 
        case ACCESS_FLOAT:
1078
 
            /* Floating point load/store */
1079
 
            return -4;
1080
 
        case ACCESS_RES:
1081
 
            /* lwarx, ldarx or srwcx. */
1082
 
            return -4;
1083
 
        case ACCESS_CACHE:
1084
 
            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
1085
 
            /* Should make the instruction do no-op.
1086
 
             * As it already do no-op, it's quite easy :-)
1087
 
             */
1088
 
            ctx->raddr = eaddr;
1089
 
            return 0;
1090
 
        case ACCESS_EXT:
1091
 
            /* eciwx or ecowx */
1092
 
            return -4;
1093
 
        default:
1094
 
            if (logfile) {
1095
 
                fprintf(logfile, "ERROR: instruction should not need "
1096
 
                        "address translation\n");
1097
 
            }
1098
 
            return -4;
1099
 
        }
1100
 
        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
1101
 
            ctx->raddr = eaddr;
1102
 
            ret = 2;
1103
 
        } else {
1104
 
            ret = -2;
1105
 
        }
1106
 
    }
1107
 
 
1108
 
    return ret;
1109
 
}
1110
 
 
1111
 
/* Generic TLB check function for embedded PowerPC implementations */
1112
 
static always_inline int ppcemb_tlb_check (CPUState *env, ppcemb_tlb_t *tlb,
1113
 
                                           target_phys_addr_t *raddrp,
1114
 
                                           target_ulong address,
1115
 
                                           uint32_t pid, int ext, int i)
1116
 
{
1117
 
    target_ulong mask;
1118
 
 
1119
 
    /* Check valid flag */
1120
 
    if (!(tlb->prot & PAGE_VALID)) {
1121
 
        if (loglevel != 0)
1122
 
            fprintf(logfile, "%s: TLB %d not valid\n", __func__, i);
1123
 
        return -1;
1124
 
    }
1125
 
    mask = ~(tlb->size - 1);
1126
 
#if defined (DEBUG_SOFTWARE_TLB)
1127
 
    if (loglevel != 0) {
1128
 
        fprintf(logfile, "%s: TLB %d address " ADDRX " PID %u <=> " ADDRX
1129
 
                " " ADDRX " %u\n",
1130
 
                __func__, i, address, pid, tlb->EPN, mask, (uint32_t)tlb->PID);
1131
 
    }
1132
 
#endif
1133
 
    /* Check PID */
1134
 
    if (tlb->PID != 0 && tlb->PID != pid)
1135
 
        return -1;
1136
 
    /* Check effective address */
1137
 
    if ((address & mask) != tlb->EPN)
1138
 
        return -1;
1139
 
    *raddrp = (tlb->RPN & mask) | (address & ~mask);
1140
 
#if (TARGET_PHYS_ADDR_BITS >= 36)
1141
 
    if (ext) {
1142
 
        /* Extend the physical address to 36 bits */
1143
 
        *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1144
 
    }
1145
 
#endif
1146
 
 
1147
 
    return 0;
1148
 
}
1149
 
 
1150
 
/* Generic TLB search function for PowerPC embedded implementations */
1151
 
int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1152
 
{
1153
 
    ppcemb_tlb_t *tlb;
1154
 
    target_phys_addr_t raddr;
1155
 
    int i, ret;
1156
 
 
1157
 
    /* Default return value is no match */
1158
 
    ret = -1;
1159
 
    for (i = 0; i < env->nb_tlb; i++) {
1160
 
        tlb = &env->tlb[i].tlbe;
1161
 
        if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1162
 
            ret = i;
1163
 
            break;
1164
 
        }
1165
 
    }
1166
 
 
1167
 
    return ret;
1168
 
}
1169
 
 
1170
 
/* Helpers specific to PowerPC 40x implementations */
1171
 
static always_inline void ppc4xx_tlb_invalidate_all (CPUState *env)
1172
 
{
1173
 
    ppcemb_tlb_t *tlb;
1174
 
    int i;
1175
 
 
1176
 
    for (i = 0; i < env->nb_tlb; i++) {
1177
 
        tlb = &env->tlb[i].tlbe;
1178
 
        tlb->prot &= ~PAGE_VALID;
1179
 
    }
1180
 
    tlb_flush(env, 1);
1181
 
}
1182
 
 
1183
 
static always_inline void ppc4xx_tlb_invalidate_virt (CPUState *env,
1184
 
                                                      target_ulong eaddr,
1185
 
                                                      uint32_t pid)
1186
 
{
1187
 
#if !defined(FLUSH_ALL_TLBS)
1188
 
    ppcemb_tlb_t *tlb;
1189
 
    target_phys_addr_t raddr;
1190
 
    target_ulong page, end;
1191
 
    int i;
1192
 
 
1193
 
    for (i = 0; i < env->nb_tlb; i++) {
1194
 
        tlb = &env->tlb[i].tlbe;
1195
 
        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1196
 
            end = tlb->EPN + tlb->size;
1197
 
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1198
 
                tlb_flush_page(env, page);
1199
 
            tlb->prot &= ~PAGE_VALID;
1200
 
            break;
1201
 
        }
1202
 
    }
1203
 
#else
1204
 
    ppc4xx_tlb_invalidate_all(env);
1205
 
#endif
1206
 
}
1207
 
 
1208
 
int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1209
 
                                 target_ulong address, int rw, int access_type)
1210
 
{
1211
 
    ppcemb_tlb_t *tlb;
1212
 
    target_phys_addr_t raddr;
1213
 
    int i, ret, zsel, zpr, pr;
1214
 
 
1215
 
    ret = -1;
1216
 
    raddr = (target_phys_addr_t)-1ULL;
1217
 
    pr = msr_pr;
1218
 
    for (i = 0; i < env->nb_tlb; i++) {
1219
 
        tlb = &env->tlb[i].tlbe;
1220
 
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1221
 
                             env->spr[SPR_40x_PID], 0, i) < 0)
1222
 
            continue;
1223
 
        zsel = (tlb->attr >> 4) & 0xF;
1224
 
        zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
1225
 
#if defined (DEBUG_SOFTWARE_TLB)
1226
 
        if (loglevel != 0) {
1227
 
            fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1228
 
                    __func__, i, zsel, zpr, rw, tlb->attr);
1229
 
        }
1230
 
#endif
1231
 
        /* Check execute enable bit */
1232
 
        switch (zpr) {
1233
 
        case 0x2:
1234
 
            if (pr != 0)
1235
 
                goto check_perms;
1236
 
            /* No break here */
1237
 
        case 0x3:
1238
 
            /* All accesses granted */
1239
 
            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1240
 
            ret = 0;
1241
 
            break;
1242
 
        case 0x0:
1243
 
            if (pr != 0) {
1244
 
                ctx->prot = 0;
1245
 
                ret = -2;
1246
 
                break;
1247
 
            }
1248
 
            /* No break here */
1249
 
        case 0x1:
1250
 
        check_perms:
1251
 
            /* Check from TLB entry */
1252
 
            /* XXX: there is a problem here or in the TLB fill code... */
1253
 
            ctx->prot = tlb->prot;
1254
 
            ctx->prot |= PAGE_EXEC;
1255
 
            ret = check_prot(ctx->prot, rw, access_type);
1256
 
            break;
1257
 
        }
1258
 
        if (ret >= 0) {
1259
 
            ctx->raddr = raddr;
1260
 
#if defined (DEBUG_SOFTWARE_TLB)
1261
 
            if (loglevel != 0) {
1262
 
                fprintf(logfile, "%s: access granted " ADDRX " => " PADDRX
1263
 
                        " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1264
 
                        ret);
1265
 
            }
1266
 
#endif
1267
 
            return 0;
1268
 
        }
1269
 
    }
1270
 
#if defined (DEBUG_SOFTWARE_TLB)
1271
 
    if (loglevel != 0) {
1272
 
        fprintf(logfile, "%s: access refused " ADDRX " => " PADDRX
1273
 
                " %d %d\n", __func__, address, raddr, ctx->prot,
1274
 
                ret);
1275
 
    }
1276
 
#endif
1277
 
 
1278
 
    return ret;
1279
 
}
1280
 
 
1281
 
void store_40x_sler (CPUPPCState *env, uint32_t val)
1282
 
{
1283
 
    /* XXX: TO BE FIXED */
1284
 
    if (val != 0x00000000) {
1285
 
        cpu_abort(env, "Little-endian regions are not supported by now\n");
1286
 
    }
1287
 
    env->spr[SPR_405_SLER] = val;
1288
 
}
1289
 
 
1290
 
int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1291
 
                                   target_ulong address, int rw,
1292
 
                                   int access_type)
1293
 
{
1294
 
    ppcemb_tlb_t *tlb;
1295
 
    target_phys_addr_t raddr;
1296
 
    int i, prot, ret;
1297
 
 
1298
 
    ret = -1;
1299
 
    raddr = (target_phys_addr_t)-1ULL;
1300
 
    for (i = 0; i < env->nb_tlb; i++) {
1301
 
        tlb = &env->tlb[i].tlbe;
1302
 
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1303
 
                             env->spr[SPR_BOOKE_PID], 1, i) < 0)
1304
 
            continue;
1305
 
        if (msr_pr != 0)
1306
 
            prot = tlb->prot & 0xF;
1307
 
        else
1308
 
            prot = (tlb->prot >> 4) & 0xF;
1309
 
        /* Check the address space */
1310
 
        if (access_type == ACCESS_CODE) {
1311
 
            if (msr_ir != (tlb->attr & 1))
1312
 
                continue;
1313
 
            ctx->prot = prot;
1314
 
            if (prot & PAGE_EXEC) {
1315
 
                ret = 0;
1316
 
                break;
1317
 
            }
1318
 
            ret = -3;
1319
 
        } else {
1320
 
            if (msr_dr != (tlb->attr & 1))
1321
 
                continue;
1322
 
            ctx->prot = prot;
1323
 
            if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
1324
 
                ret = 0;
1325
 
                break;
1326
 
            }
1327
 
            ret = -2;
1328
 
        }
1329
 
    }
1330
 
    if (ret >= 0)
1331
 
        ctx->raddr = raddr;
1332
 
 
1333
 
    return ret;
1334
 
}
1335
 
 
1336
 
static always_inline int check_physical (CPUState *env, mmu_ctx_t *ctx,
1337
 
                                         target_ulong eaddr, int rw)
1338
 
{
1339
 
    int in_plb, ret;
1340
 
 
1341
 
    ctx->raddr = eaddr;
1342
 
    ctx->prot = PAGE_READ | PAGE_EXEC;
1343
 
    ret = 0;
1344
 
    switch (env->mmu_model) {
1345
 
    case POWERPC_MMU_32B:
1346
 
    case POWERPC_MMU_601:
1347
 
    case POWERPC_MMU_SOFT_6xx:
1348
 
    case POWERPC_MMU_SOFT_74xx:
1349
 
    case POWERPC_MMU_SOFT_4xx:
1350
 
    case POWERPC_MMU_REAL:
1351
 
    case POWERPC_MMU_BOOKE:
1352
 
        ctx->prot |= PAGE_WRITE;
1353
 
        break;
1354
 
#if defined(TARGET_PPC64)
1355
 
    case POWERPC_MMU_620:
1356
 
    case POWERPC_MMU_64B:
1357
 
        /* Real address are 60 bits long */
1358
 
        ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1359
 
        ctx->prot |= PAGE_WRITE;
1360
 
        break;
1361
 
#endif
1362
 
    case POWERPC_MMU_SOFT_4xx_Z:
1363
 
        if (unlikely(msr_pe != 0)) {
1364
 
            /* 403 family add some particular protections,
1365
 
             * using PBL/PBU registers for accesses with no translation.
1366
 
             */
1367
 
            in_plb =
1368
 
                /* Check PLB validity */
1369
 
                (env->pb[0] < env->pb[1] &&
1370
 
                 /* and address in plb area */
1371
 
                 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1372
 
                (env->pb[2] < env->pb[3] &&
1373
 
                 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1374
 
            if (in_plb ^ msr_px) {
1375
 
                /* Access in protected area */
1376
 
                if (rw == 1) {
1377
 
                    /* Access is not allowed */
1378
 
                    ret = -2;
1379
 
                }
1380
 
            } else {
1381
 
                /* Read-write access is allowed */
1382
 
                ctx->prot |= PAGE_WRITE;
1383
 
            }
1384
 
        }
1385
 
        break;
1386
 
    case POWERPC_MMU_MPC8xx:
1387
 
        /* XXX: TODO */
1388
 
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1389
 
        break;
1390
 
    case POWERPC_MMU_BOOKE_FSL:
1391
 
        /* XXX: TODO */
1392
 
        cpu_abort(env, "BookE FSL MMU model not implemented\n");
1393
 
        break;
1394
 
    default:
1395
 
        cpu_abort(env, "Unknown or invalid MMU model\n");
1396
 
        return -1;
1397
 
    }
1398
 
 
1399
 
    return ret;
1400
 
}
1401
 
 
1402
 
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1403
 
                          int rw, int access_type)
1404
 
{
1405
 
    int ret;
1406
 
 
1407
 
#if 0
1408
 
    if (loglevel != 0) {
1409
 
        fprintf(logfile, "%s\n", __func__);
1410
 
    }
1411
 
#endif
1412
 
    if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1413
 
        (access_type != ACCESS_CODE && msr_dr == 0)) {
1414
 
        /* No address translation */
1415
 
        ret = check_physical(env, ctx, eaddr, rw);
1416
 
    } else {
1417
 
        ret = -1;
1418
 
        switch (env->mmu_model) {
1419
 
        case POWERPC_MMU_32B:
1420
 
        case POWERPC_MMU_601:
1421
 
        case POWERPC_MMU_SOFT_6xx:
1422
 
        case POWERPC_MMU_SOFT_74xx:
1423
 
#if defined(TARGET_PPC64)
1424
 
        case POWERPC_MMU_620:
1425
 
        case POWERPC_MMU_64B:
1426
 
#endif
1427
 
            /* Try to find a BAT */
1428
 
            if (env->nb_BATs != 0)
1429
 
                ret = get_bat(env, ctx, eaddr, rw, access_type);
1430
 
            if (ret < 0) {
1431
 
                /* We didn't match any BAT entry or don't have BATs */
1432
 
                ret = get_segment(env, ctx, eaddr, rw, access_type);
1433
 
            }
1434
 
            break;
1435
 
        case POWERPC_MMU_SOFT_4xx:
1436
 
        case POWERPC_MMU_SOFT_4xx_Z:
1437
 
            ret = mmu40x_get_physical_address(env, ctx, eaddr,
1438
 
                                              rw, access_type);
1439
 
            break;
1440
 
        case POWERPC_MMU_BOOKE:
1441
 
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1442
 
                                                rw, access_type);
1443
 
            break;
1444
 
        case POWERPC_MMU_MPC8xx:
1445
 
            /* XXX: TODO */
1446
 
            cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1447
 
            break;
1448
 
        case POWERPC_MMU_BOOKE_FSL:
1449
 
            /* XXX: TODO */
1450
 
            cpu_abort(env, "BookE FSL MMU model not implemented\n");
1451
 
            return -1;
1452
 
        case POWERPC_MMU_REAL:
1453
 
            cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1454
 
            return -1;
1455
 
        default:
1456
 
            cpu_abort(env, "Unknown or invalid MMU model\n");
1457
 
            return -1;
1458
 
        }
1459
 
    }
1460
 
#if 0
1461
 
    if (loglevel != 0) {
1462
 
        fprintf(logfile, "%s address " ADDRX " => %d " PADDRX "\n",
1463
 
                __func__, eaddr, ret, ctx->raddr);
1464
 
    }
1465
 
#endif
1466
 
 
1467
 
    return ret;
1468
 
}
1469
 
 
1470
 
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1471
 
{
1472
 
    mmu_ctx_t ctx;
1473
 
 
1474
 
    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1475
 
        return -1;
1476
 
 
1477
 
    return ctx.raddr & TARGET_PAGE_MASK;
1478
 
}
1479
 
 
1480
 
/* Perform address translation */
1481
 
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1482
 
                              int mmu_idx, int is_softmmu)
1483
 
{
1484
 
    mmu_ctx_t ctx;
1485
 
    int access_type;
1486
 
    int ret = 0;
1487
 
 
1488
 
    if (rw == 2) {
1489
 
        /* code access */
1490
 
        rw = 0;
1491
 
        access_type = ACCESS_CODE;
1492
 
    } else {
1493
 
        /* data access */
1494
 
        /* XXX: put correct access by using cpu_restore_state()
1495
 
           correctly */
1496
 
        access_type = ACCESS_INT;
1497
 
        //        access_type = env->access_type;
1498
 
    }
1499
 
    ret = get_physical_address(env, &ctx, address, rw, access_type);
1500
 
    if (ret == 0) {
1501
 
        ret = tlb_set_page_exec(env, address & TARGET_PAGE_MASK,
1502
 
                                ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1503
 
                                mmu_idx, is_softmmu);
1504
 
    } else if (ret < 0) {
1505
 
#if defined (DEBUG_MMU)
1506
 
        if (loglevel != 0)
1507
 
            cpu_dump_state(env, logfile, fprintf, 0);
1508
 
#endif
1509
 
        if (access_type == ACCESS_CODE) {
1510
 
            switch (ret) {
1511
 
            case -1:
1512
 
                /* No matches in page tables or TLB */
1513
 
                switch (env->mmu_model) {
1514
 
                case POWERPC_MMU_SOFT_6xx:
1515
 
                    env->exception_index = POWERPC_EXCP_IFTLB;
1516
 
                    env->error_code = 1 << 18;
1517
 
                    env->spr[SPR_IMISS] = address;
1518
 
                    env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1519
 
                    goto tlb_miss;
1520
 
                case POWERPC_MMU_SOFT_74xx:
1521
 
                    env->exception_index = POWERPC_EXCP_IFTLB;
1522
 
                    goto tlb_miss_74xx;
1523
 
                case POWERPC_MMU_SOFT_4xx:
1524
 
                case POWERPC_MMU_SOFT_4xx_Z:
1525
 
                    env->exception_index = POWERPC_EXCP_ITLB;
1526
 
                    env->error_code = 0;
1527
 
                    env->spr[SPR_40x_DEAR] = address;
1528
 
                    env->spr[SPR_40x_ESR] = 0x00000000;
1529
 
                    break;
1530
 
                case POWERPC_MMU_32B:
1531
 
                case POWERPC_MMU_601:
1532
 
#if defined(TARGET_PPC64)
1533
 
                case POWERPC_MMU_620:
1534
 
                case POWERPC_MMU_64B:
1535
 
#endif
1536
 
                    env->exception_index = POWERPC_EXCP_ISI;
1537
 
                    env->error_code = 0x40000000;
1538
 
                    break;
1539
 
                case POWERPC_MMU_BOOKE:
1540
 
                    /* XXX: TODO */
1541
 
                    cpu_abort(env, "BookE MMU model is not implemented\n");
1542
 
                    return -1;
1543
 
                case POWERPC_MMU_BOOKE_FSL:
1544
 
                    /* XXX: TODO */
1545
 
                    cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1546
 
                    return -1;
1547
 
                case POWERPC_MMU_MPC8xx:
1548
 
                    /* XXX: TODO */
1549
 
                    cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1550
 
                    break;
1551
 
                case POWERPC_MMU_REAL:
1552
 
                    cpu_abort(env, "PowerPC in real mode should never raise "
1553
 
                              "any MMU exceptions\n");
1554
 
                    return -1;
1555
 
                default:
1556
 
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1557
 
                    return -1;
1558
 
                }
1559
 
                break;
1560
 
            case -2:
1561
 
                /* Access rights violation */
1562
 
                env->exception_index = POWERPC_EXCP_ISI;
1563
 
                env->error_code = 0x08000000;
1564
 
                break;
1565
 
            case -3:
1566
 
                /* No execute protection violation */
1567
 
                env->exception_index = POWERPC_EXCP_ISI;
1568
 
                env->error_code = 0x10000000;
1569
 
                break;
1570
 
            case -4:
1571
 
                /* Direct store exception */
1572
 
                /* No code fetch is allowed in direct-store areas */
1573
 
                env->exception_index = POWERPC_EXCP_ISI;
1574
 
                env->error_code = 0x10000000;
1575
 
                break;
1576
 
#if defined(TARGET_PPC64)
1577
 
            case -5:
1578
 
                /* No match in segment table */
1579
 
                if (env->mmu_model == POWERPC_MMU_620) {
1580
 
                    env->exception_index = POWERPC_EXCP_ISI;
1581
 
                    /* XXX: this might be incorrect */
1582
 
                    env->error_code = 0x40000000;
1583
 
                } else {
1584
 
                    env->exception_index = POWERPC_EXCP_ISEG;
1585
 
                    env->error_code = 0;
1586
 
                }
1587
 
                break;
1588
 
#endif
1589
 
            }
1590
 
        } else {
1591
 
            switch (ret) {
1592
 
            case -1:
1593
 
                /* No matches in page tables or TLB */
1594
 
                switch (env->mmu_model) {
1595
 
                case POWERPC_MMU_SOFT_6xx:
1596
 
                    if (rw == 1) {
1597
 
                        env->exception_index = POWERPC_EXCP_DSTLB;
1598
 
                        env->error_code = 1 << 16;
1599
 
                    } else {
1600
 
                        env->exception_index = POWERPC_EXCP_DLTLB;
1601
 
                        env->error_code = 0;
1602
 
                    }
1603
 
                    env->spr[SPR_DMISS] = address;
1604
 
                    env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1605
 
                tlb_miss:
1606
 
                    env->error_code |= ctx.key << 19;
1607
 
                    env->spr[SPR_HASH1] = ctx.pg_addr[0];
1608
 
                    env->spr[SPR_HASH2] = ctx.pg_addr[1];
1609
 
                    break;
1610
 
                case POWERPC_MMU_SOFT_74xx:
1611
 
                    if (rw == 1) {
1612
 
                        env->exception_index = POWERPC_EXCP_DSTLB;
1613
 
                    } else {
1614
 
                        env->exception_index = POWERPC_EXCP_DLTLB;
1615
 
                    }
1616
 
                tlb_miss_74xx:
1617
 
                    /* Implement LRU algorithm */
1618
 
                    env->error_code = ctx.key << 19;
1619
 
                    env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1620
 
                        ((env->last_way + 1) & (env->nb_ways - 1));
1621
 
                    env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1622
 
                    break;
1623
 
                case POWERPC_MMU_SOFT_4xx:
1624
 
                case POWERPC_MMU_SOFT_4xx_Z:
1625
 
                    env->exception_index = POWERPC_EXCP_DTLB;
1626
 
                    env->error_code = 0;
1627
 
                    env->spr[SPR_40x_DEAR] = address;
1628
 
                    if (rw)
1629
 
                        env->spr[SPR_40x_ESR] = 0x00800000;
1630
 
                    else
1631
 
                        env->spr[SPR_40x_ESR] = 0x00000000;
1632
 
                    break;
1633
 
                case POWERPC_MMU_32B:
1634
 
                case POWERPC_MMU_601:
1635
 
#if defined(TARGET_PPC64)
1636
 
                case POWERPC_MMU_620:
1637
 
                case POWERPC_MMU_64B:
1638
 
#endif
1639
 
                    env->exception_index = POWERPC_EXCP_DSI;
1640
 
                    env->error_code = 0;
1641
 
                    env->spr[SPR_DAR] = address;
1642
 
                    if (rw == 1)
1643
 
                        env->spr[SPR_DSISR] = 0x42000000;
1644
 
                    else
1645
 
                        env->spr[SPR_DSISR] = 0x40000000;
1646
 
                    break;
1647
 
                case POWERPC_MMU_MPC8xx:
1648
 
                    /* XXX: TODO */
1649
 
                    cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1650
 
                    break;
1651
 
                case POWERPC_MMU_BOOKE:
1652
 
                    /* XXX: TODO */
1653
 
                    cpu_abort(env, "BookE MMU model is not implemented\n");
1654
 
                    return -1;
1655
 
                case POWERPC_MMU_BOOKE_FSL:
1656
 
                    /* XXX: TODO */
1657
 
                    cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1658
 
                    return -1;
1659
 
                case POWERPC_MMU_REAL:
1660
 
                    cpu_abort(env, "PowerPC in real mode should never raise "
1661
 
                              "any MMU exceptions\n");
1662
 
                    return -1;
1663
 
                default:
1664
 
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1665
 
                    return -1;
1666
 
                }
1667
 
                break;
1668
 
            case -2:
1669
 
                /* Access rights violation */
1670
 
                env->exception_index = POWERPC_EXCP_DSI;
1671
 
                env->error_code = 0;
1672
 
                env->spr[SPR_DAR] = address;
1673
 
                if (rw == 1)
1674
 
                    env->spr[SPR_DSISR] = 0x0A000000;
1675
 
                else
1676
 
                    env->spr[SPR_DSISR] = 0x08000000;
1677
 
                break;
1678
 
            case -4:
1679
 
                /* Direct store exception */
1680
 
                switch (access_type) {
1681
 
                case ACCESS_FLOAT:
1682
 
                    /* Floating point load/store */
1683
 
                    env->exception_index = POWERPC_EXCP_ALIGN;
1684
 
                    env->error_code = POWERPC_EXCP_ALIGN_FP;
1685
 
                    env->spr[SPR_DAR] = address;
1686
 
                    break;
1687
 
                case ACCESS_RES:
1688
 
                    /* lwarx, ldarx or stwcx. */
1689
 
                    env->exception_index = POWERPC_EXCP_DSI;
1690
 
                    env->error_code = 0;
1691
 
                    env->spr[SPR_DAR] = address;
1692
 
                    if (rw == 1)
1693
 
                        env->spr[SPR_DSISR] = 0x06000000;
1694
 
                    else
1695
 
                        env->spr[SPR_DSISR] = 0x04000000;
1696
 
                    break;
1697
 
                case ACCESS_EXT:
1698
 
                    /* eciwx or ecowx */
1699
 
                    env->exception_index = POWERPC_EXCP_DSI;
1700
 
                    env->error_code = 0;
1701
 
                    env->spr[SPR_DAR] = address;
1702
 
                    if (rw == 1)
1703
 
                        env->spr[SPR_DSISR] = 0x06100000;
1704
 
                    else
1705
 
                        env->spr[SPR_DSISR] = 0x04100000;
1706
 
                    break;
1707
 
                default:
1708
 
                    printf("DSI: invalid exception (%d)\n", ret);
1709
 
                    env->exception_index = POWERPC_EXCP_PROGRAM;
1710
 
                    env->error_code =
1711
 
                        POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1712
 
                    env->spr[SPR_DAR] = address;
1713
 
                    break;
1714
 
                }
1715
 
                break;
1716
 
#if defined(TARGET_PPC64)
1717
 
            case -5:
1718
 
                /* No match in segment table */
1719
 
                if (env->mmu_model == POWERPC_MMU_620) {
1720
 
                    env->exception_index = POWERPC_EXCP_DSI;
1721
 
                    env->error_code = 0;
1722
 
                    env->spr[SPR_DAR] = address;
1723
 
                    /* XXX: this might be incorrect */
1724
 
                    if (rw == 1)
1725
 
                        env->spr[SPR_DSISR] = 0x42000000;
1726
 
                    else
1727
 
                        env->spr[SPR_DSISR] = 0x40000000;
1728
 
                } else {
1729
 
                    env->exception_index = POWERPC_EXCP_DSEG;
1730
 
                    env->error_code = 0;
1731
 
                    env->spr[SPR_DAR] = address;
1732
 
                }
1733
 
                break;
1734
 
#endif
1735
 
            }
1736
 
        }
1737
 
#if 0
1738
 
        printf("%s: set exception to %d %02x\n", __func__,
1739
 
               env->exception, env->error_code);
1740
 
#endif
1741
 
        ret = 1;
1742
 
    }
1743
 
 
1744
 
    return ret;
1745
 
}
1746
 
 
1747
 
/*****************************************************************************/
1748
 
/* BATs management */
1749
 
#if !defined(FLUSH_ALL_TLBS)
1750
 
static always_inline void do_invalidate_BAT (CPUPPCState *env,
1751
 
                                             target_ulong BATu,
1752
 
                                             target_ulong mask)
1753
 
{
1754
 
    target_ulong base, end, page;
1755
 
 
1756
 
    base = BATu & ~0x0001FFFF;
1757
 
    end = base + mask + 0x00020000;
1758
 
#if defined (DEBUG_BATS)
1759
 
    if (loglevel != 0) {
1760
 
        fprintf(logfile, "Flush BAT from " ADDRX " to " ADDRX " (" ADDRX ")\n",
1761
 
                base, end, mask);
1762
 
    }
1763
 
#endif
1764
 
    for (page = base; page != end; page += TARGET_PAGE_SIZE)
1765
 
        tlb_flush_page(env, page);
1766
 
#if defined (DEBUG_BATS)
1767
 
    if (loglevel != 0)
1768
 
        fprintf(logfile, "Flush done\n");
1769
 
#endif
1770
 
}
1771
 
#endif
1772
 
 
1773
 
static always_inline void dump_store_bat (CPUPPCState *env, char ID,
1774
 
                                          int ul, int nr, target_ulong value)
1775
 
{
1776
 
#if defined (DEBUG_BATS)
1777
 
    if (loglevel != 0) {
1778
 
        fprintf(logfile, "Set %cBAT%d%c to " ADDRX " (" ADDRX ")\n",
1779
 
                ID, nr, ul == 0 ? 'u' : 'l', value, env->nip);
1780
 
    }
1781
 
#endif
1782
 
}
1783
 
 
1784
 
target_ulong do_load_ibatu (CPUPPCState *env, int nr)
1785
 
{
1786
 
    return env->IBAT[0][nr];
1787
 
}
1788
 
 
1789
 
target_ulong do_load_ibatl (CPUPPCState *env, int nr)
1790
 
{
1791
 
    return env->IBAT[1][nr];
1792
 
}
1793
 
 
1794
 
void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1795
 
{
1796
 
    target_ulong mask;
1797
 
 
1798
 
    dump_store_bat(env, 'I', 0, nr, value);
1799
 
    if (env->IBAT[0][nr] != value) {
1800
 
        mask = (value << 15) & 0x0FFE0000UL;
1801
 
#if !defined(FLUSH_ALL_TLBS)
1802
 
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1803
 
#endif
1804
 
        /* When storing valid upper BAT, mask BEPI and BRPN
1805
 
         * and invalidate all TLBs covered by this BAT
1806
 
         */
1807
 
        mask = (value << 15) & 0x0FFE0000UL;
1808
 
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1809
 
            (value & ~0x0001FFFFUL & ~mask);
1810
 
        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1811
 
            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1812
 
#if !defined(FLUSH_ALL_TLBS)
1813
 
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1814
 
#else
1815
 
        tlb_flush(env, 1);
1816
 
#endif
1817
 
    }
1818
 
}
1819
 
 
1820
 
void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1821
 
{
1822
 
    dump_store_bat(env, 'I', 1, nr, value);
1823
 
    env->IBAT[1][nr] = value;
1824
 
}
1825
 
 
1826
 
target_ulong do_load_dbatu (CPUPPCState *env, int nr)
1827
 
{
1828
 
    return env->DBAT[0][nr];
1829
 
}
1830
 
 
1831
 
target_ulong do_load_dbatl (CPUPPCState *env, int nr)
1832
 
{
1833
 
    return env->DBAT[1][nr];
1834
 
}
1835
 
 
1836
 
void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1837
 
{
1838
 
    target_ulong mask;
1839
 
 
1840
 
    dump_store_bat(env, 'D', 0, nr, value);
1841
 
    if (env->DBAT[0][nr] != value) {
1842
 
        /* When storing valid upper BAT, mask BEPI and BRPN
1843
 
         * and invalidate all TLBs covered by this BAT
1844
 
         */
1845
 
        mask = (value << 15) & 0x0FFE0000UL;
1846
 
#if !defined(FLUSH_ALL_TLBS)
1847
 
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1848
 
#endif
1849
 
        mask = (value << 15) & 0x0FFE0000UL;
1850
 
        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1851
 
            (value & ~0x0001FFFFUL & ~mask);
1852
 
        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1853
 
            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1854
 
#if !defined(FLUSH_ALL_TLBS)
1855
 
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1856
 
#else
1857
 
        tlb_flush(env, 1);
1858
 
#endif
1859
 
    }
1860
 
}
1861
 
 
1862
 
void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1863
 
{
1864
 
    dump_store_bat(env, 'D', 1, nr, value);
1865
 
    env->DBAT[1][nr] = value;
1866
 
}
1867
 
 
1868
 
void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1869
 
{
1870
 
    target_ulong mask;
1871
 
    int do_inval;
1872
 
 
1873
 
    dump_store_bat(env, 'I', 0, nr, value);
1874
 
    if (env->IBAT[0][nr] != value) {
1875
 
        do_inval = 0;
1876
 
        mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1877
 
        if (env->IBAT[1][nr] & 0x40) {
1878
 
            /* Invalidate BAT only if it is valid */
1879
 
#if !defined(FLUSH_ALL_TLBS)
1880
 
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1881
 
#else
1882
 
            do_inval = 1;
1883
 
#endif
1884
 
        }
1885
 
        /* When storing valid upper BAT, mask BEPI and BRPN
1886
 
         * and invalidate all TLBs covered by this BAT
1887
 
         */
1888
 
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1889
 
            (value & ~0x0001FFFFUL & ~mask);
1890
 
        env->DBAT[0][nr] = env->IBAT[0][nr];
1891
 
        if (env->IBAT[1][nr] & 0x40) {
1892
 
#if !defined(FLUSH_ALL_TLBS)
1893
 
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1894
 
#else
1895
 
            do_inval = 1;
1896
 
#endif
1897
 
        }
1898
 
#if defined(FLUSH_ALL_TLBS)
1899
 
        if (do_inval)
1900
 
            tlb_flush(env, 1);
1901
 
#endif
1902
 
    }
1903
 
}
1904
 
 
1905
 
void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1906
 
{
1907
 
    target_ulong mask;
1908
 
    int do_inval;
1909
 
 
1910
 
    dump_store_bat(env, 'I', 1, nr, value);
1911
 
    if (env->IBAT[1][nr] != value) {
1912
 
        do_inval = 0;
1913
 
        if (env->IBAT[1][nr] & 0x40) {
1914
 
#if !defined(FLUSH_ALL_TLBS)
1915
 
            mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1916
 
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1917
 
#else
1918
 
            do_inval = 1;
1919
 
#endif
1920
 
        }
1921
 
        if (value & 0x40) {
1922
 
#if !defined(FLUSH_ALL_TLBS)
1923
 
            mask = (value << 17) & 0x0FFE0000UL;
1924
 
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1925
 
#else
1926
 
            do_inval = 1;
1927
 
#endif
1928
 
        }
1929
 
        env->IBAT[1][nr] = value;
1930
 
        env->DBAT[1][nr] = value;
1931
 
#if defined(FLUSH_ALL_TLBS)
1932
 
        if (do_inval)
1933
 
            tlb_flush(env, 1);
1934
 
#endif
1935
 
    }
1936
 
}
1937
 
 
1938
 
/*****************************************************************************/
1939
 
/* TLB management */
1940
 
void ppc_tlb_invalidate_all (CPUPPCState *env)
1941
 
{
1942
 
    switch (env->mmu_model) {
1943
 
    case POWERPC_MMU_SOFT_6xx:
1944
 
    case POWERPC_MMU_SOFT_74xx:
1945
 
        ppc6xx_tlb_invalidate_all(env);
1946
 
        break;
1947
 
    case POWERPC_MMU_SOFT_4xx:
1948
 
    case POWERPC_MMU_SOFT_4xx_Z:
1949
 
        ppc4xx_tlb_invalidate_all(env);
1950
 
        break;
1951
 
    case POWERPC_MMU_REAL:
1952
 
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1953
 
        break;
1954
 
    case POWERPC_MMU_MPC8xx:
1955
 
        /* XXX: TODO */
1956
 
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1957
 
        break;
1958
 
    case POWERPC_MMU_BOOKE:
1959
 
        /* XXX: TODO */
1960
 
        cpu_abort(env, "BookE MMU model is not implemented\n");
1961
 
        break;
1962
 
    case POWERPC_MMU_BOOKE_FSL:
1963
 
        /* XXX: TODO */
1964
 
        cpu_abort(env, "BookE MMU model is not implemented\n");
1965
 
        break;
1966
 
    case POWERPC_MMU_32B:
1967
 
    case POWERPC_MMU_601:
1968
 
#if defined(TARGET_PPC64)
1969
 
    case POWERPC_MMU_620:
1970
 
    case POWERPC_MMU_64B:
1971
 
#endif /* defined(TARGET_PPC64) */
1972
 
        tlb_flush(env, 1);
1973
 
        break;
1974
 
    default:
1975
 
        /* XXX: TODO */
1976
 
        cpu_abort(env, "Unknown MMU model\n");
1977
 
        break;
1978
 
    }
1979
 
}
1980
 
 
1981
 
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
1982
 
{
1983
 
#if !defined(FLUSH_ALL_TLBS)
1984
 
    addr &= TARGET_PAGE_MASK;
1985
 
    switch (env->mmu_model) {
1986
 
    case POWERPC_MMU_SOFT_6xx:
1987
 
    case POWERPC_MMU_SOFT_74xx:
1988
 
        ppc6xx_tlb_invalidate_virt(env, addr, 0);
1989
 
        if (env->id_tlbs == 1)
1990
 
            ppc6xx_tlb_invalidate_virt(env, addr, 1);
1991
 
        break;
1992
 
    case POWERPC_MMU_SOFT_4xx:
1993
 
    case POWERPC_MMU_SOFT_4xx_Z:
1994
 
        ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
1995
 
        break;
1996
 
    case POWERPC_MMU_REAL:
1997
 
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1998
 
        break;
1999
 
    case POWERPC_MMU_MPC8xx:
2000
 
        /* XXX: TODO */
2001
 
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2002
 
        break;
2003
 
    case POWERPC_MMU_BOOKE:
2004
 
        /* XXX: TODO */
2005
 
        cpu_abort(env, "BookE MMU model is not implemented\n");
2006
 
        break;
2007
 
    case POWERPC_MMU_BOOKE_FSL:
2008
 
        /* XXX: TODO */
2009
 
        cpu_abort(env, "BookE FSL MMU model is not implemented\n");
2010
 
        break;
2011
 
    case POWERPC_MMU_32B:
2012
 
    case POWERPC_MMU_601:
2013
 
        /* tlbie invalidate TLBs for all segments */
2014
 
        addr &= ~((target_ulong)-1ULL << 28);
2015
 
        /* XXX: this case should be optimized,
2016
 
         * giving a mask to tlb_flush_page
2017
 
         */
2018
 
        tlb_flush_page(env, addr | (0x0 << 28));
2019
 
        tlb_flush_page(env, addr | (0x1 << 28));
2020
 
        tlb_flush_page(env, addr | (0x2 << 28));
2021
 
        tlb_flush_page(env, addr | (0x3 << 28));
2022
 
        tlb_flush_page(env, addr | (0x4 << 28));
2023
 
        tlb_flush_page(env, addr | (0x5 << 28));
2024
 
        tlb_flush_page(env, addr | (0x6 << 28));
2025
 
        tlb_flush_page(env, addr | (0x7 << 28));
2026
 
        tlb_flush_page(env, addr | (0x8 << 28));
2027
 
        tlb_flush_page(env, addr | (0x9 << 28));
2028
 
        tlb_flush_page(env, addr | (0xA << 28));
2029
 
        tlb_flush_page(env, addr | (0xB << 28));
2030
 
        tlb_flush_page(env, addr | (0xC << 28));
2031
 
        tlb_flush_page(env, addr | (0xD << 28));
2032
 
        tlb_flush_page(env, addr | (0xE << 28));
2033
 
        tlb_flush_page(env, addr | (0xF << 28));
2034
 
        break;
2035
 
#if defined(TARGET_PPC64)
2036
 
    case POWERPC_MMU_620:
2037
 
    case POWERPC_MMU_64B:
2038
 
        /* tlbie invalidate TLBs for all segments */
2039
 
        /* XXX: given the fact that there are too many segments to invalidate,
2040
 
         *      and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
2041
 
         *      we just invalidate all TLBs
2042
 
         */
2043
 
        tlb_flush(env, 1);
2044
 
        break;
2045
 
#endif /* defined(TARGET_PPC64) */
2046
 
    default:
2047
 
        /* XXX: TODO */
2048
 
        cpu_abort(env, "Unknown MMU model\n");
2049
 
        break;
2050
 
    }
2051
 
#else
2052
 
    ppc_tlb_invalidate_all(env);
2053
 
#endif
2054
 
}
2055
 
 
2056
 
/*****************************************************************************/
2057
 
/* Special registers manipulation */
2058
 
#if defined(TARGET_PPC64)
2059
 
target_ulong ppc_load_asr (CPUPPCState *env)
2060
 
{
2061
 
    return env->asr;
2062
 
}
2063
 
 
2064
 
void ppc_store_asr (CPUPPCState *env, target_ulong value)
2065
 
{
2066
 
    if (env->asr != value) {
2067
 
        env->asr = value;
2068
 
        tlb_flush(env, 1);
2069
 
    }
2070
 
}
2071
 
#endif
2072
 
 
2073
 
target_ulong do_load_sdr1 (CPUPPCState *env)
2074
 
{
2075
 
    return env->sdr1;
2076
 
}
2077
 
 
2078
 
void do_store_sdr1 (CPUPPCState *env, target_ulong value)
2079
 
{
2080
 
#if defined (DEBUG_MMU)
2081
 
    if (loglevel != 0) {
2082
 
        fprintf(logfile, "%s: " ADDRX "\n", __func__, value);
2083
 
    }
2084
 
#endif
2085
 
    if (env->sdr1 != value) {
2086
 
        /* XXX: for PowerPC 64, should check that the HTABSIZE value
2087
 
         *      is <= 28
2088
 
         */
2089
 
        env->sdr1 = value;
2090
 
        tlb_flush(env, 1);
2091
 
    }
2092
 
}
2093
 
 
2094
 
#if 0 // Unused
2095
 
target_ulong do_load_sr (CPUPPCState *env, int srnum)
2096
 
{
2097
 
    return env->sr[srnum];
2098
 
}
2099
 
#endif
2100
 
 
2101
 
void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
2102
 
{
2103
 
#if defined (DEBUG_MMU)
2104
 
    if (loglevel != 0) {
2105
 
        fprintf(logfile, "%s: reg=%d " ADDRX " " ADDRX "\n",
2106
 
                __func__, srnum, value, env->sr[srnum]);
2107
 
    }
2108
 
#endif
2109
 
    if (env->sr[srnum] != value) {
2110
 
        env->sr[srnum] = value;
2111
 
#if !defined(FLUSH_ALL_TLBS) && 0
2112
 
        {
2113
 
            target_ulong page, end;
2114
 
            /* Invalidate 256 MB of virtual memory */
2115
 
            page = (16 << 20) * srnum;
2116
 
            end = page + (16 << 20);
2117
 
            for (; page != end; page += TARGET_PAGE_SIZE)
2118
 
                tlb_flush_page(env, page);
2119
 
        }
2120
 
#else
2121
 
        tlb_flush(env, 1);
2122
 
#endif
2123
 
    }
2124
 
}
2125
 
#endif /* !defined (CONFIG_USER_ONLY) */
2126
 
 
2127
 
/* GDBstub can read and write MSR... */
2128
 
void ppc_store_msr (CPUPPCState *env, target_ulong value)
2129
 
{
2130
 
    hreg_store_msr(env, value, 0);
2131
 
}
2132
 
 
2133
 
/*****************************************************************************/
2134
 
/* Exception processing */
2135
 
#if defined (CONFIG_USER_ONLY)
2136
 
void do_interrupt (CPUState *env)
2137
 
{
2138
 
    env->exception_index = POWERPC_EXCP_NONE;
2139
 
    env->error_code = 0;
2140
 
}
2141
 
 
2142
 
void ppc_hw_interrupt (CPUState *env)
2143
 
{
2144
 
    env->exception_index = POWERPC_EXCP_NONE;
2145
 
    env->error_code = 0;
2146
 
}
2147
 
#else /* defined (CONFIG_USER_ONLY) */
2148
 
static always_inline void dump_syscall (CPUState *env)
2149
 
{
2150
 
    fprintf(logfile, "syscall r0=" REGX " r3=" REGX " r4=" REGX
2151
 
            " r5=" REGX " r6=" REGX " nip=" ADDRX "\n",
2152
 
            ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4),
2153
 
            ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6), env->nip);
2154
 
}
2155
 
 
2156
 
/* Note that this function should be greatly optimized
2157
 
 * when called with a constant excp, from ppc_hw_interrupt
2158
 
 */
2159
 
static always_inline void powerpc_excp (CPUState *env,
2160
 
                                        int excp_model, int excp)
2161
 
{
2162
 
    target_ulong msr, new_msr, vector;
2163
 
    int srr0, srr1, asrr0, asrr1;
2164
 
    int lpes0, lpes1, lev;
2165
 
 
2166
 
    if (0) {
2167
 
        /* XXX: find a suitable condition to enable the hypervisor mode */
2168
 
        lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2169
 
        lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2170
 
    } else {
2171
 
        /* Those values ensure we won't enter the hypervisor mode */
2172
 
        lpes0 = 0;
2173
 
        lpes1 = 1;
2174
 
    }
2175
 
 
2176
 
    if (loglevel & CPU_LOG_INT) {
2177
 
        fprintf(logfile, "Raise exception at " ADDRX " => %08x (%02x)\n",
2178
 
                env->nip, excp, env->error_code);
2179
 
    }
2180
 
    msr = env->msr;
2181
 
    new_msr = msr;
2182
 
    srr0 = SPR_SRR0;
2183
 
    srr1 = SPR_SRR1;
2184
 
    asrr0 = -1;
2185
 
    asrr1 = -1;
2186
 
    msr &= ~((target_ulong)0x783F0000);
2187
 
    switch (excp) {
2188
 
    case POWERPC_EXCP_NONE:
2189
 
        /* Should never happen */
2190
 
        return;
2191
 
    case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
2192
 
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2193
 
        switch (excp_model) {
2194
 
        case POWERPC_EXCP_40x:
2195
 
            srr0 = SPR_40x_SRR2;
2196
 
            srr1 = SPR_40x_SRR3;
2197
 
            break;
2198
 
        case POWERPC_EXCP_BOOKE:
2199
 
            srr0 = SPR_BOOKE_CSRR0;
2200
 
            srr1 = SPR_BOOKE_CSRR1;
2201
 
            break;
2202
 
        case POWERPC_EXCP_G2:
2203
 
            break;
2204
 
        default:
2205
 
            goto excp_invalid;
2206
 
        }
2207
 
        goto store_next;
2208
 
    case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
2209
 
        if (msr_me == 0) {
2210
 
            /* Machine check exception is not enabled.
2211
 
             * Enter checkstop state.
2212
 
             */
2213
 
            if (loglevel != 0) {
2214
 
                fprintf(logfile, "Machine check while not allowed. "
2215
 
                        "Entering checkstop state\n");
2216
 
            } else {
2217
 
                fprintf(stderr, "Machine check while not allowed. "
2218
 
                        "Entering checkstop state\n");
2219
 
            }
2220
 
            env->halted = 1;
2221
 
            env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2222
 
        }
2223
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2224
 
        new_msr &= ~((target_ulong)1 << MSR_ME);
2225
 
        if (0) {
2226
 
            /* XXX: find a suitable condition to enable the hypervisor mode */
2227
 
            new_msr |= (target_ulong)MSR_HVB;
2228
 
        }
2229
 
        /* XXX: should also have something loaded in DAR / DSISR */
2230
 
        switch (excp_model) {
2231
 
        case POWERPC_EXCP_40x:
2232
 
            srr0 = SPR_40x_SRR2;
2233
 
            srr1 = SPR_40x_SRR3;
2234
 
            break;
2235
 
        case POWERPC_EXCP_BOOKE:
2236
 
            srr0 = SPR_BOOKE_MCSRR0;
2237
 
            srr1 = SPR_BOOKE_MCSRR1;
2238
 
            asrr0 = SPR_BOOKE_CSRR0;
2239
 
            asrr1 = SPR_BOOKE_CSRR1;
2240
 
            break;
2241
 
        default:
2242
 
            break;
2243
 
        }
2244
 
        goto store_next;
2245
 
    case POWERPC_EXCP_DSI:       /* Data storage exception                   */
2246
 
#if defined (DEBUG_EXCEPTIONS)
2247
 
        if (loglevel != 0) {
2248
 
            fprintf(logfile, "DSI exception: DSISR=" ADDRX" DAR=" ADDRX "\n",
2249
 
                    env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2250
 
        }
2251
 
#endif
2252
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2253
 
        if (lpes1 == 0)
2254
 
            new_msr |= (target_ulong)MSR_HVB;
2255
 
        goto store_next;
2256
 
    case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
2257
 
#if defined (DEBUG_EXCEPTIONS)
2258
 
        if (loglevel != 0) {
2259
 
            fprintf(logfile, "ISI exception: msr=" ADDRX ", nip=" ADDRX "\n",
2260
 
                    msr, env->nip);
2261
 
        }
2262
 
#endif
2263
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2264
 
        if (lpes1 == 0)
2265
 
            new_msr |= (target_ulong)MSR_HVB;
2266
 
        msr |= env->error_code;
2267
 
        goto store_next;
2268
 
    case POWERPC_EXCP_EXTERNAL:  /* External input                           */
2269
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2270
 
        if (lpes0 == 1)
2271
 
            new_msr |= (target_ulong)MSR_HVB;
2272
 
        goto store_next;
2273
 
    case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
2274
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2275
 
        if (lpes1 == 0)
2276
 
            new_msr |= (target_ulong)MSR_HVB;
2277
 
        /* XXX: this is false */
2278
 
        /* Get rS/rD and rA from faulting opcode */
2279
 
        env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2280
 
        goto store_current;
2281
 
    case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
2282
 
        switch (env->error_code & ~0xF) {
2283
 
        case POWERPC_EXCP_FP:
2284
 
            if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2285
 
#if defined (DEBUG_EXCEPTIONS)
2286
 
                if (loglevel != 0) {
2287
 
                    fprintf(logfile, "Ignore floating point exception\n");
2288
 
                }
2289
 
#endif
2290
 
                env->exception_index = POWERPC_EXCP_NONE;
2291
 
                env->error_code = 0;
2292
 
                return;
2293
 
            }
2294
 
            new_msr &= ~((target_ulong)1 << MSR_RI);
2295
 
            if (lpes1 == 0)
2296
 
                new_msr |= (target_ulong)MSR_HVB;
2297
 
            msr |= 0x00100000;
2298
 
            if (msr_fe0 == msr_fe1)
2299
 
                goto store_next;
2300
 
            msr |= 0x00010000;
2301
 
            break;
2302
 
        case POWERPC_EXCP_INVAL:
2303
 
#if defined (DEBUG_EXCEPTIONS)
2304
 
            if (loglevel != 0) {
2305
 
                fprintf(logfile, "Invalid instruction at " ADDRX "\n",
2306
 
                        env->nip);
2307
 
            }
2308
 
#endif
2309
 
            new_msr &= ~((target_ulong)1 << MSR_RI);
2310
 
            if (lpes1 == 0)
2311
 
                new_msr |= (target_ulong)MSR_HVB;
2312
 
            msr |= 0x00080000;
2313
 
            break;
2314
 
        case POWERPC_EXCP_PRIV:
2315
 
            new_msr &= ~((target_ulong)1 << MSR_RI);
2316
 
            if (lpes1 == 0)
2317
 
                new_msr |= (target_ulong)MSR_HVB;
2318
 
            msr |= 0x00040000;
2319
 
            break;
2320
 
        case POWERPC_EXCP_TRAP:
2321
 
            new_msr &= ~((target_ulong)1 << MSR_RI);
2322
 
            if (lpes1 == 0)
2323
 
                new_msr |= (target_ulong)MSR_HVB;
2324
 
            msr |= 0x00020000;
2325
 
            break;
2326
 
        default:
2327
 
            /* Should never occur */
2328
 
            cpu_abort(env, "Invalid program exception %d. Aborting\n",
2329
 
                      env->error_code);
2330
 
            break;
2331
 
        }
2332
 
        goto store_current;
2333
 
    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
2334
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2335
 
        if (lpes1 == 0)
2336
 
            new_msr |= (target_ulong)MSR_HVB;
2337
 
        goto store_current;
2338
 
    case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
2339
 
        /* NOTE: this is a temporary hack to support graphics OSI
2340
 
           calls from the MOL driver */
2341
 
        /* XXX: To be removed */
2342
 
        if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
2343
 
            env->osi_call) {
2344
 
            if (env->osi_call(env) != 0) {
2345
 
                env->exception_index = POWERPC_EXCP_NONE;
2346
 
                env->error_code = 0;
2347
 
                return;
2348
 
            }
2349
 
        }
2350
 
        if (loglevel & CPU_LOG_INT) {
2351
 
            dump_syscall(env);
2352
 
        }
2353
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2354
 
        lev = env->error_code;
2355
 
        if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2356
 
            new_msr |= (target_ulong)MSR_HVB;
2357
 
        goto store_next;
2358
 
    case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
2359
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2360
 
        goto store_current;
2361
 
    case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
2362
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2363
 
        if (lpes1 == 0)
2364
 
            new_msr |= (target_ulong)MSR_HVB;
2365
 
        goto store_next;
2366
 
    case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
2367
 
        /* FIT on 4xx */
2368
 
#if defined (DEBUG_EXCEPTIONS)
2369
 
        if (loglevel != 0)
2370
 
            fprintf(logfile, "FIT exception\n");
2371
 
#endif
2372
 
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2373
 
        goto store_next;
2374
 
    case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
2375
 
#if defined (DEBUG_EXCEPTIONS)
2376
 
        if (loglevel != 0)
2377
 
            fprintf(logfile, "WDT exception\n");
2378
 
#endif
2379
 
        switch (excp_model) {
2380
 
        case POWERPC_EXCP_BOOKE:
2381
 
            srr0 = SPR_BOOKE_CSRR0;
2382
 
            srr1 = SPR_BOOKE_CSRR1;
2383
 
            break;
2384
 
        default:
2385
 
            break;
2386
 
        }
2387
 
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2388
 
        goto store_next;
2389
 
    case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
2390
 
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2391
 
        goto store_next;
2392
 
    case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
2393
 
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2394
 
        goto store_next;
2395
 
    case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
2396
 
        switch (excp_model) {
2397
 
        case POWERPC_EXCP_BOOKE:
2398
 
            srr0 = SPR_BOOKE_DSRR0;
2399
 
            srr1 = SPR_BOOKE_DSRR1;
2400
 
            asrr0 = SPR_BOOKE_CSRR0;
2401
 
            asrr1 = SPR_BOOKE_CSRR1;
2402
 
            break;
2403
 
        default:
2404
 
            break;
2405
 
        }
2406
 
        /* XXX: TODO */
2407
 
        cpu_abort(env, "Debug exception is not implemented yet !\n");
2408
 
        goto store_next;
2409
 
    case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
2410
 
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2411
 
        goto store_current;
2412
 
    case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
2413
 
        /* XXX: TODO */
2414
 
        cpu_abort(env, "Embedded floating point data exception "
2415
 
                  "is not implemented yet !\n");
2416
 
        goto store_next;
2417
 
    case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
2418
 
        /* XXX: TODO */
2419
 
        cpu_abort(env, "Embedded floating point round exception "
2420
 
                  "is not implemented yet !\n");
2421
 
        goto store_next;
2422
 
    case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
2423
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2424
 
        /* XXX: TODO */
2425
 
        cpu_abort(env,
2426
 
                  "Performance counter exception is not implemented yet !\n");
2427
 
        goto store_next;
2428
 
    case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
2429
 
        /* XXX: TODO */
2430
 
        cpu_abort(env,
2431
 
                  "Embedded doorbell interrupt is not implemented yet !\n");
2432
 
        goto store_next;
2433
 
    case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
2434
 
        switch (excp_model) {
2435
 
        case POWERPC_EXCP_BOOKE:
2436
 
            srr0 = SPR_BOOKE_CSRR0;
2437
 
            srr1 = SPR_BOOKE_CSRR1;
2438
 
            break;
2439
 
        default:
2440
 
            break;
2441
 
        }
2442
 
        /* XXX: TODO */
2443
 
        cpu_abort(env, "Embedded doorbell critical interrupt "
2444
 
                  "is not implemented yet !\n");
2445
 
        goto store_next;
2446
 
    case POWERPC_EXCP_RESET:     /* System reset exception                   */
2447
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2448
 
        if (0) {
2449
 
            /* XXX: find a suitable condition to enable the hypervisor mode */
2450
 
            new_msr |= (target_ulong)MSR_HVB;
2451
 
        }
2452
 
        goto store_next;
2453
 
    case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
2454
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2455
 
        if (lpes1 == 0)
2456
 
            new_msr |= (target_ulong)MSR_HVB;
2457
 
        goto store_next;
2458
 
    case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
2459
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2460
 
        if (lpes1 == 0)
2461
 
            new_msr |= (target_ulong)MSR_HVB;
2462
 
        goto store_next;
2463
 
    case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
2464
 
        srr0 = SPR_HSRR0;
2465
 
        srr1 = SPR_HSRR1;
2466
 
        new_msr |= (target_ulong)MSR_HVB;
2467
 
        goto store_next;
2468
 
    case POWERPC_EXCP_TRACE:     /* Trace exception                          */
2469
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2470
 
        if (lpes1 == 0)
2471
 
            new_msr |= (target_ulong)MSR_HVB;
2472
 
        goto store_next;
2473
 
    case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
2474
 
        srr0 = SPR_HSRR0;
2475
 
        srr1 = SPR_HSRR1;
2476
 
        new_msr |= (target_ulong)MSR_HVB;
2477
 
        goto store_next;
2478
 
    case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
2479
 
        srr0 = SPR_HSRR0;
2480
 
        srr1 = SPR_HSRR1;
2481
 
        new_msr |= (target_ulong)MSR_HVB;
2482
 
        goto store_next;
2483
 
    case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
2484
 
        srr0 = SPR_HSRR0;
2485
 
        srr1 = SPR_HSRR1;
2486
 
        new_msr |= (target_ulong)MSR_HVB;
2487
 
        goto store_next;
2488
 
    case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
2489
 
        srr0 = SPR_HSRR0;
2490
 
        srr1 = SPR_HSRR1;
2491
 
        new_msr |= (target_ulong)MSR_HVB;
2492
 
        goto store_next;
2493
 
    case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
2494
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2495
 
        if (lpes1 == 0)
2496
 
            new_msr |= (target_ulong)MSR_HVB;
2497
 
        goto store_current;
2498
 
    case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
2499
 
#if defined (DEBUG_EXCEPTIONS)
2500
 
        if (loglevel != 0)
2501
 
            fprintf(logfile, "PIT exception\n");
2502
 
#endif
2503
 
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2504
 
        goto store_next;
2505
 
    case POWERPC_EXCP_IO:        /* IO error exception                       */
2506
 
        /* XXX: TODO */
2507
 
        cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2508
 
        goto store_next;
2509
 
    case POWERPC_EXCP_RUNM:      /* Run mode exception                       */
2510
 
        /* XXX: TODO */
2511
 
        cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2512
 
        goto store_next;
2513
 
    case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 */
2514
 
        /* XXX: TODO */
2515
 
        cpu_abort(env, "602 emulation trap exception "
2516
 
                  "is not implemented yet !\n");
2517
 
        goto store_next;
2518
 
    case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
2519
 
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2520
 
        if (lpes1 == 0) /* XXX: check this */
2521
 
            new_msr |= (target_ulong)MSR_HVB;
2522
 
        switch (excp_model) {
2523
 
        case POWERPC_EXCP_602:
2524
 
        case POWERPC_EXCP_603:
2525
 
        case POWERPC_EXCP_603E:
2526
 
        case POWERPC_EXCP_G2:
2527
 
            goto tlb_miss_tgpr;
2528
 
        case POWERPC_EXCP_7x5:
2529
 
            goto tlb_miss;
2530
 
        case POWERPC_EXCP_74xx:
2531
 
            goto tlb_miss_74xx;
2532
 
        default:
2533
 
            cpu_abort(env, "Invalid instruction TLB miss exception\n");
2534
 
            break;
2535
 
        }
2536
 
        break;
2537
 
    case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
2538
 
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2539
 
        if (lpes1 == 0) /* XXX: check this */
2540
 
            new_msr |= (target_ulong)MSR_HVB;
2541
 
        switch (excp_model) {
2542
 
        case POWERPC_EXCP_602:
2543
 
        case POWERPC_EXCP_603:
2544
 
        case POWERPC_EXCP_603E:
2545
 
        case POWERPC_EXCP_G2:
2546
 
            goto tlb_miss_tgpr;
2547
 
        case POWERPC_EXCP_7x5:
2548
 
            goto tlb_miss;
2549
 
        case POWERPC_EXCP_74xx:
2550
 
            goto tlb_miss_74xx;
2551
 
        default:
2552
 
            cpu_abort(env, "Invalid data load TLB miss exception\n");
2553
 
            break;
2554
 
        }
2555
 
        break;
2556
 
    case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
2557
 
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2558
 
        if (lpes1 == 0) /* XXX: check this */
2559
 
            new_msr |= (target_ulong)MSR_HVB;
2560
 
        switch (excp_model) {
2561
 
        case POWERPC_EXCP_602:
2562
 
        case POWERPC_EXCP_603:
2563
 
        case POWERPC_EXCP_603E:
2564
 
        case POWERPC_EXCP_G2:
2565
 
        tlb_miss_tgpr:
2566
 
            /* Swap temporary saved registers with GPRs */
2567
 
            if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2568
 
                new_msr |= (target_ulong)1 << MSR_TGPR;
2569
 
                hreg_swap_gpr_tgpr(env);
2570
 
            }
2571
 
            goto tlb_miss;
2572
 
        case POWERPC_EXCP_7x5:
2573
 
        tlb_miss:
2574
 
#if defined (DEBUG_SOFTWARE_TLB)
2575
 
            if (loglevel != 0) {
2576
 
                const unsigned char *es;
2577
 
                target_ulong *miss, *cmp;
2578
 
                int en;
2579
 
                if (excp == POWERPC_EXCP_IFTLB) {
2580
 
                    es = "I";
2581
 
                    en = 'I';
2582
 
                    miss = &env->spr[SPR_IMISS];
2583
 
                    cmp = &env->spr[SPR_ICMP];
2584
 
                } else {
2585
 
                    if (excp == POWERPC_EXCP_DLTLB)
2586
 
                        es = "DL";
2587
 
                    else
2588
 
                        es = "DS";
2589
 
                    en = 'D';
2590
 
                    miss = &env->spr[SPR_DMISS];
2591
 
                    cmp = &env->spr[SPR_DCMP];
2592
 
                }
2593
 
                fprintf(logfile, "6xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
2594
 
                        " H1 " ADDRX " H2 " ADDRX " %08x\n",
2595
 
                        es, en, *miss, en, *cmp,
2596
 
                        env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2597
 
                        env->error_code);
2598
 
            }
2599
 
#endif
2600
 
            msr |= env->crf[0] << 28;
2601
 
            msr |= env->error_code; /* key, D/I, S/L bits */
2602
 
            /* Set way using a LRU mechanism */
2603
 
            msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2604
 
            break;
2605
 
        case POWERPC_EXCP_74xx:
2606
 
        tlb_miss_74xx:
2607
 
#if defined (DEBUG_SOFTWARE_TLB)
2608
 
            if (loglevel != 0) {
2609
 
                const unsigned char *es;
2610
 
                target_ulong *miss, *cmp;
2611
 
                int en;
2612
 
                if (excp == POWERPC_EXCP_IFTLB) {
2613
 
                    es = "I";
2614
 
                    en = 'I';
2615
 
                    miss = &env->spr[SPR_TLBMISS];
2616
 
                    cmp = &env->spr[SPR_PTEHI];
2617
 
                } else {
2618
 
                    if (excp == POWERPC_EXCP_DLTLB)
2619
 
                        es = "DL";
2620
 
                    else
2621
 
                        es = "DS";
2622
 
                    en = 'D';
2623
 
                    miss = &env->spr[SPR_TLBMISS];
2624
 
                    cmp = &env->spr[SPR_PTEHI];
2625
 
                }
2626
 
                fprintf(logfile, "74xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
2627
 
                        " %08x\n",
2628
 
                        es, en, *miss, en, *cmp, env->error_code);
2629
 
            }
2630
 
#endif
2631
 
            msr |= env->error_code; /* key bit */
2632
 
            break;
2633
 
        default:
2634
 
            cpu_abort(env, "Invalid data store TLB miss exception\n");
2635
 
            break;
2636
 
        }
2637
 
        goto store_next;
2638
 
    case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
2639
 
        /* XXX: TODO */
2640
 
        cpu_abort(env, "Floating point assist exception "
2641
 
                  "is not implemented yet !\n");
2642
 
        goto store_next;
2643
 
    case POWERPC_EXCP_DABR:      /* Data address breakpoint                  */
2644
 
        /* XXX: TODO */
2645
 
        cpu_abort(env, "DABR exception is not implemented yet !\n");
2646
 
        goto store_next;
2647
 
    case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
2648
 
        /* XXX: TODO */
2649
 
        cpu_abort(env, "IABR exception is not implemented yet !\n");
2650
 
        goto store_next;
2651
 
    case POWERPC_EXCP_SMI:       /* System management interrupt              */
2652
 
        /* XXX: TODO */
2653
 
        cpu_abort(env, "SMI exception is not implemented yet !\n");
2654
 
        goto store_next;
2655
 
    case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
2656
 
        /* XXX: TODO */
2657
 
        cpu_abort(env, "Thermal management exception "
2658
 
                  "is not implemented yet !\n");
2659
 
        goto store_next;
2660
 
    case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
2661
 
        new_msr &= ~((target_ulong)1 << MSR_RI);
2662
 
        if (lpes1 == 0)
2663
 
            new_msr |= (target_ulong)MSR_HVB;
2664
 
        /* XXX: TODO */
2665
 
        cpu_abort(env,
2666
 
                  "Performance counter exception is not implemented yet !\n");
2667
 
        goto store_next;
2668
 
    case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
2669
 
        /* XXX: TODO */
2670
 
        cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2671
 
        goto store_next;
2672
 
    case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
2673
 
        /* XXX: TODO */
2674
 
        cpu_abort(env,
2675
 
                  "970 soft-patch exception is not implemented yet !\n");
2676
 
        goto store_next;
2677
 
    case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
2678
 
        /* XXX: TODO */
2679
 
        cpu_abort(env,
2680
 
                  "970 maintenance exception is not implemented yet !\n");
2681
 
        goto store_next;
2682
 
    case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             */
2683
 
        /* XXX: TODO */
2684
 
        cpu_abort(env, "Maskable external exception "
2685
 
                  "is not implemented yet !\n");
2686
 
        goto store_next;
2687
 
    case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         */
2688
 
        /* XXX: TODO */
2689
 
        cpu_abort(env, "Non maskable external exception "
2690
 
                  "is not implemented yet !\n");
2691
 
        goto store_next;
2692
 
    default:
2693
 
    excp_invalid:
2694
 
        cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2695
 
        break;
2696
 
    store_current:
2697
 
        /* save current instruction location */
2698
 
        env->spr[srr0] = env->nip - 4;
2699
 
        break;
2700
 
    store_next:
2701
 
        /* save next instruction location */
2702
 
        env->spr[srr0] = env->nip;
2703
 
        break;
2704
 
    }
2705
 
    /* Save MSR */
2706
 
    env->spr[srr1] = msr;
2707
 
    /* If any alternate SRR register are defined, duplicate saved values */
2708
 
    if (asrr0 != -1)
2709
 
        env->spr[asrr0] = env->spr[srr0];
2710
 
    if (asrr1 != -1)
2711
 
        env->spr[asrr1] = env->spr[srr1];
2712
 
    /* If we disactivated any translation, flush TLBs */
2713
 
    if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2714
 
        tlb_flush(env, 1);
2715
 
    /* reload MSR with correct bits */
2716
 
    new_msr &= ~((target_ulong)1 << MSR_EE);
2717
 
    new_msr &= ~((target_ulong)1 << MSR_PR);
2718
 
    new_msr &= ~((target_ulong)1 << MSR_FP);
2719
 
    new_msr &= ~((target_ulong)1 << MSR_FE0);
2720
 
    new_msr &= ~((target_ulong)1 << MSR_SE);
2721
 
    new_msr &= ~((target_ulong)1 << MSR_BE);
2722
 
    new_msr &= ~((target_ulong)1 << MSR_FE1);
2723
 
    new_msr &= ~((target_ulong)1 << MSR_IR);
2724
 
    new_msr &= ~((target_ulong)1 << MSR_DR);
2725
 
#if 0 /* Fix this: not on all targets */
2726
 
    new_msr &= ~((target_ulong)1 << MSR_PMM);
2727
 
#endif
2728
 
    new_msr &= ~((target_ulong)1 << MSR_LE);
2729
 
    if (msr_ile)
2730
 
        new_msr |= (target_ulong)1 << MSR_LE;
2731
 
    else
2732
 
        new_msr &= ~((target_ulong)1 << MSR_LE);
2733
 
    /* Jump to handler */
2734
 
    vector = env->excp_vectors[excp];
2735
 
    if (vector == (target_ulong)-1ULL) {
2736
 
        cpu_abort(env, "Raised an exception without defined vector %d\n",
2737
 
                  excp);
2738
 
    }
2739
 
    vector |= env->excp_prefix;
2740
 
#if defined(TARGET_PPC64)
2741
 
    if (excp_model == POWERPC_EXCP_BOOKE) {
2742
 
        if (!msr_icm) {
2743
 
            new_msr &= ~((target_ulong)1 << MSR_CM);
2744
 
            vector = (uint32_t)vector;
2745
 
        } else {
2746
 
            new_msr |= (target_ulong)1 << MSR_CM;
2747
 
        }
2748
 
    } else {
2749
 
        if (!msr_isf) {
2750
 
            new_msr &= ~((target_ulong)1 << MSR_SF);
2751
 
            vector = (uint32_t)vector;
2752
 
        } else {
2753
 
            new_msr |= (target_ulong)1 << MSR_SF;
2754
 
        }
2755
 
    }
2756
 
#endif
2757
 
    /* XXX: we don't use hreg_store_msr here as already have treated
2758
 
     *      any special case that could occur. Just store MSR and update hflags
2759
 
     */
2760
 
    env->msr = new_msr & env->msr_mask;
2761
 
    hreg_compute_hflags(env);
2762
 
    env->nip = vector;
2763
 
    /* Reset exception state */
2764
 
    env->exception_index = POWERPC_EXCP_NONE;
2765
 
    env->error_code = 0;
2766
 
}
2767
 
 
2768
 
void do_interrupt (CPUState *env)
2769
 
{
2770
 
    powerpc_excp(env, env->excp_model, env->exception_index);
2771
 
}
2772
 
 
2773
 
void ppc_hw_interrupt (CPUPPCState *env)
2774
 
{
2775
 
    int hdice;
2776
 
 
2777
 
#if 0
2778
 
    if (loglevel & CPU_LOG_INT) {
2779
 
        fprintf(logfile, "%s: %p pending %08x req %08x me %d ee %d\n",
2780
 
                __func__, env, env->pending_interrupts,
2781
 
                env->interrupt_request, (int)msr_me, (int)msr_ee);
2782
 
    }
2783
 
#endif
2784
 
    /* External reset */
2785
 
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
2786
 
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
2787
 
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
2788
 
        return;
2789
 
    }
2790
 
    /* Machine check exception */
2791
 
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
2792
 
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
2793
 
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
2794
 
        return;
2795
 
    }
2796
 
#if 0 /* TODO */
2797
 
    /* External debug exception */
2798
 
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
2799
 
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2800
 
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
2801
 
        return;
2802
 
    }
2803
 
#endif
2804
 
    if (0) {
2805
 
        /* XXX: find a suitable condition to enable the hypervisor mode */
2806
 
        hdice = env->spr[SPR_LPCR] & 1;
2807
 
    } else {
2808
 
        hdice = 0;
2809
 
    }
2810
 
    if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
2811
 
        /* Hypervisor decrementer exception */
2812
 
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
2813
 
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
2814
 
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
2815
 
            return;
2816
 
        }
2817
 
    }
2818
 
    if (msr_ce != 0) {
2819
 
        /* External critical interrupt */
2820
 
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
2821
 
            /* Taking a critical external interrupt does not clear the external
2822
 
             * critical interrupt status
2823
 
             */
2824
 
#if 0
2825
 
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
2826
 
#endif
2827
 
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
2828
 
            return;
2829
 
        }
2830
 
    }
2831
 
    if (msr_ee != 0) {
2832
 
        /* Watchdog timer on embedded PowerPC */
2833
 
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
2834
 
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
2835
 
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
2836
 
            return;
2837
 
        }
2838
 
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
2839
 
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
2840
 
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
2841
 
            return;
2842
 
        }
2843
 
        /* Fixed interval timer on embedded PowerPC */
2844
 
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
2845
 
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
2846
 
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
2847
 
            return;
2848
 
        }
2849
 
        /* Programmable interval timer on embedded PowerPC */
2850
 
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
2851
 
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
2852
 
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
2853
 
            return;
2854
 
        }
2855
 
        /* Decrementer exception */
2856
 
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
2857
 
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
2858
 
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
2859
 
            return;
2860
 
        }
2861
 
        /* External interrupt */
2862
 
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
2863
 
            /* Taking an external interrupt does not clear the external
2864
 
             * interrupt status
2865
 
             */
2866
 
#if 0
2867
 
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
2868
 
#endif
2869
 
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
2870
 
            return;
2871
 
        }
2872
 
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
2873
 
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2874
 
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
2875
 
            return;
2876
 
        }
2877
 
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
2878
 
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
2879
 
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
2880
 
            return;
2881
 
        }
2882
 
        /* Thermal interrupt */
2883
 
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
2884
 
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
2885
 
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
2886
 
            return;
2887
 
        }
2888
 
    }
2889
 
}
2890
 
#endif /* !CONFIG_USER_ONLY */
2891
 
 
2892
 
void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2893
 
{
2894
 
    FILE *f;
2895
 
 
2896
 
    if (logfile) {
2897
 
        f = logfile;
2898
 
    } else {
2899
 
        f = stdout;
2900
 
        return;
2901
 
    }
2902
 
    fprintf(f, "Return from exception at " ADDRX " with flags " ADDRX "\n",
2903
 
            RA, msr);
2904
 
}
2905
 
 
2906
 
void cpu_ppc_reset (void *opaque)
2907
 
{
2908
 
    CPUPPCState *env;
2909
 
    target_ulong msr;
2910
 
 
2911
 
    env = opaque;
2912
 
    msr = (target_ulong)0;
2913
 
    if (0) {
2914
 
        /* XXX: find a suitable condition to enable the hypervisor mode */
2915
 
        msr |= (target_ulong)MSR_HVB;
2916
 
    }
2917
 
    msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
2918
 
    msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
2919
 
    msr |= (target_ulong)1 << MSR_EP;
2920
 
#if defined (DO_SINGLE_STEP) && 0
2921
 
    /* Single step trace mode */
2922
 
    msr |= (target_ulong)1 << MSR_SE;
2923
 
    msr |= (target_ulong)1 << MSR_BE;
2924
 
#endif
2925
 
#if defined(CONFIG_USER_ONLY)
2926
 
    msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
2927
 
    msr |= (target_ulong)1 << MSR_PR;
2928
 
#else
2929
 
    env->nip = env->hreset_vector | env->excp_prefix;
2930
 
    if (env->mmu_model != POWERPC_MMU_REAL)
2931
 
        ppc_tlb_invalidate_all(env);
2932
 
#endif
2933
 
    env->msr = msr;
2934
 
    hreg_compute_hflags(env);
2935
 
    env->reserve = (target_ulong)-1ULL;
2936
 
    /* Be sure no exception or interrupt is pending */
2937
 
    env->pending_interrupts = 0;
2938
 
    env->exception_index = POWERPC_EXCP_NONE;
2939
 
    env->error_code = 0;
2940
 
    /* Flush all TLBs */
2941
 
    tlb_flush(env, 1);
2942
 
}
2943
 
 
2944
 
CPUPPCState *cpu_ppc_init (const char *cpu_model)
2945
 
{
2946
 
    CPUPPCState *env;
2947
 
    const ppc_def_t *def;
2948
 
 
2949
 
    def = cpu_ppc_find_by_name(cpu_model);
2950
 
    if (!def)
2951
 
        return NULL;
2952
 
 
2953
 
    env = qemu_mallocz(sizeof(CPUPPCState));
2954
 
    if (!env)
2955
 
        return NULL;
2956
 
    cpu_exec_init(env);
2957
 
    ppc_translate_init();
2958
 
    env->cpu_model_str = cpu_model;
2959
 
    cpu_ppc_register_internal(env, def);
2960
 
    cpu_ppc_reset(env);
2961
 
    return env;
2962
 
}
2963
 
 
2964
 
void cpu_ppc_close (CPUPPCState *env)
2965
 
{
2966
 
    /* Should also remove all opcode tables... */
2967
 
    qemu_free(env);
2968
 
}