Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ a22f123c

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