Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ fda6a0ec

History | View | Annotate | Download (91 kB)

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