Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ bb4ea393

History | View | Annotate | Download (92.4 kB)

1 79aceca5 bellard
/*
2 3fc6c082 bellard
 *  PowerPC emulation helpers for qemu.
3 5fafdf24 ths
 *
4 76a66253 j_mayer
 *  Copyright (c) 2003-2007 Jocelyn Mayer
5 79aceca5 bellard
 *
6 79aceca5 bellard
 * This library is free software; you can redistribute it and/or
7 79aceca5 bellard
 * modify it under the terms of the GNU Lesser General Public
8 79aceca5 bellard
 * License as published by the Free Software Foundation; either
9 79aceca5 bellard
 * version 2 of the License, or (at your option) any later version.
10 79aceca5 bellard
 *
11 79aceca5 bellard
 * This library is distributed in the hope that it will be useful,
12 79aceca5 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 79aceca5 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 79aceca5 bellard
 * Lesser General Public License for more details.
15 79aceca5 bellard
 *
16 79aceca5 bellard
 * You should have received a copy of the GNU Lesser General Public
17 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 79aceca5 bellard
 */
19 fdabc366 bellard
#include <stdarg.h>
20 fdabc366 bellard
#include <stdlib.h>
21 fdabc366 bellard
#include <stdio.h>
22 fdabc366 bellard
#include <string.h>
23 fdabc366 bellard
#include <inttypes.h>
24 fdabc366 bellard
#include <signal.h>
25 fdabc366 bellard
26 fdabc366 bellard
#include "cpu.h"
27 fdabc366 bellard
#include "exec-all.h"
28 0411a972 j_mayer
#include "helper_regs.h"
29 ca10f867 aurel32
#include "qemu-common.h"
30 d76d1650 aurel32
#include "kvm.h"
31 9a64fbe4 bellard
32 9a64fbe4 bellard
//#define DEBUG_MMU
33 9a64fbe4 bellard
//#define DEBUG_BATS
34 6b542af7 j_mayer
//#define DEBUG_SLB
35 76a66253 j_mayer
//#define DEBUG_SOFTWARE_TLB
36 0411a972 j_mayer
//#define DUMP_PAGE_TABLES
37 9a64fbe4 bellard
//#define DEBUG_EXCEPTIONS
38 fdabc366 bellard
//#define FLUSH_ALL_TLBS
39 9a64fbe4 bellard
40 d12d51d5 aliguori
#ifdef DEBUG_MMU
41 93fcfe39 aliguori
#  define LOG_MMU(...) qemu_log(__VA_ARGS__)
42 93fcfe39 aliguori
#  define LOG_MMU_STATE(env) log_cpu_state((env), 0)
43 d12d51d5 aliguori
#else
44 d12d51d5 aliguori
#  define LOG_MMU(...) do { } while (0)
45 d12d51d5 aliguori
#  define LOG_MMU_STATE(...) do { } while (0)
46 d12d51d5 aliguori
#endif
47 d12d51d5 aliguori
48 d12d51d5 aliguori
49 d12d51d5 aliguori
#ifdef DEBUG_SOFTWARE_TLB
50 93fcfe39 aliguori
#  define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
51 d12d51d5 aliguori
#else
52 d12d51d5 aliguori
#  define LOG_SWTLB(...) do { } while (0)
53 d12d51d5 aliguori
#endif
54 d12d51d5 aliguori
55 d12d51d5 aliguori
#ifdef DEBUG_BATS
56 93fcfe39 aliguori
#  define LOG_BATS(...) qemu_log(__VA_ARGS__)
57 d12d51d5 aliguori
#else
58 d12d51d5 aliguori
#  define LOG_BATS(...) do { } while (0)
59 d12d51d5 aliguori
#endif
60 d12d51d5 aliguori
61 d12d51d5 aliguori
#ifdef DEBUG_SLB
62 93fcfe39 aliguori
#  define LOG_SLB(...) qemu_log(__VA_ARGS__)
63 d12d51d5 aliguori
#else
64 d12d51d5 aliguori
#  define LOG_SLB(...) do { } while (0)
65 d12d51d5 aliguori
#endif
66 d12d51d5 aliguori
67 d12d51d5 aliguori
#ifdef DEBUG_EXCEPTIONS
68 93fcfe39 aliguori
#  define LOG_EXCP(...) qemu_log(__VA_ARGS__)
69 d12d51d5 aliguori
#else
70 d12d51d5 aliguori
#  define LOG_EXCP(...) do { } while (0)
71 d12d51d5 aliguori
#endif
72 d12d51d5 aliguori
73 d12d51d5 aliguori
74 9a64fbe4 bellard
/*****************************************************************************/
75 3fc6c082 bellard
/* PowerPC MMU emulation */
76 a541f297 bellard
77 d9bce9d9 j_mayer
#if defined(CONFIG_USER_ONLY)
78 e96efcfc j_mayer
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
79 6ebbf390 j_mayer
                              int mmu_idx, int is_softmmu)
80 24741ef3 bellard
{
81 24741ef3 bellard
    int exception, error_code;
82 d9bce9d9 j_mayer
83 24741ef3 bellard
    if (rw == 2) {
84 e1833e1f j_mayer
        exception = POWERPC_EXCP_ISI;
85 8f793433 j_mayer
        error_code = 0x40000000;
86 24741ef3 bellard
    } else {
87 e1833e1f j_mayer
        exception = POWERPC_EXCP_DSI;
88 8f793433 j_mayer
        error_code = 0x40000000;
89 24741ef3 bellard
        if (rw)
90 24741ef3 bellard
            error_code |= 0x02000000;
91 24741ef3 bellard
        env->spr[SPR_DAR] = address;
92 24741ef3 bellard
        env->spr[SPR_DSISR] = error_code;
93 24741ef3 bellard
    }
94 24741ef3 bellard
    env->exception_index = exception;
95 24741ef3 bellard
    env->error_code = error_code;
96 76a66253 j_mayer
97 24741ef3 bellard
    return 1;
98 24741ef3 bellard
}
99 76a66253 j_mayer
100 24741ef3 bellard
#else
101 76a66253 j_mayer
/* Common routines used by software and hardware TLBs emulation */
102 636aa200 Blue Swirl
static inline int pte_is_valid(target_ulong pte0)
103 76a66253 j_mayer
{
104 76a66253 j_mayer
    return pte0 & 0x80000000 ? 1 : 0;
105 76a66253 j_mayer
}
106 76a66253 j_mayer
107 636aa200 Blue Swirl
static inline void pte_invalidate(target_ulong *pte0)
108 76a66253 j_mayer
{
109 76a66253 j_mayer
    *pte0 &= ~0x80000000;
110 76a66253 j_mayer
}
111 76a66253 j_mayer
112 caa4039c j_mayer
#if defined(TARGET_PPC64)
113 636aa200 Blue Swirl
static inline int pte64_is_valid(target_ulong pte0)
114 caa4039c j_mayer
{
115 caa4039c j_mayer
    return pte0 & 0x0000000000000001ULL ? 1 : 0;
116 caa4039c j_mayer
}
117 caa4039c j_mayer
118 636aa200 Blue Swirl
static inline void pte64_invalidate(target_ulong *pte0)
119 caa4039c j_mayer
{
120 caa4039c j_mayer
    *pte0 &= ~0x0000000000000001ULL;
121 caa4039c j_mayer
}
122 caa4039c j_mayer
#endif
123 caa4039c j_mayer
124 76a66253 j_mayer
#define PTE_PTEM_MASK 0x7FFFFFBF
125 76a66253 j_mayer
#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
126 caa4039c j_mayer
#if defined(TARGET_PPC64)
127 caa4039c j_mayer
#define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
128 caa4039c j_mayer
#define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
129 caa4039c j_mayer
#endif
130 76a66253 j_mayer
131 636aa200 Blue Swirl
static inline int pp_check(int key, int pp, int nx)
132 b227a8e9 j_mayer
{
133 b227a8e9 j_mayer
    int access;
134 b227a8e9 j_mayer
135 b227a8e9 j_mayer
    /* Compute access rights */
136 b227a8e9 j_mayer
    /* When pp is 3/7, the result is undefined. Set it to noaccess */
137 b227a8e9 j_mayer
    access = 0;
138 b227a8e9 j_mayer
    if (key == 0) {
139 b227a8e9 j_mayer
        switch (pp) {
140 b227a8e9 j_mayer
        case 0x0:
141 b227a8e9 j_mayer
        case 0x1:
142 b227a8e9 j_mayer
        case 0x2:
143 b227a8e9 j_mayer
            access |= PAGE_WRITE;
144 b227a8e9 j_mayer
            /* No break here */
145 b227a8e9 j_mayer
        case 0x3:
146 b227a8e9 j_mayer
        case 0x6:
147 b227a8e9 j_mayer
            access |= PAGE_READ;
148 b227a8e9 j_mayer
            break;
149 b227a8e9 j_mayer
        }
150 b227a8e9 j_mayer
    } else {
151 b227a8e9 j_mayer
        switch (pp) {
152 b227a8e9 j_mayer
        case 0x0:
153 b227a8e9 j_mayer
        case 0x6:
154 b227a8e9 j_mayer
            access = 0;
155 b227a8e9 j_mayer
            break;
156 b227a8e9 j_mayer
        case 0x1:
157 b227a8e9 j_mayer
        case 0x3:
158 b227a8e9 j_mayer
            access = PAGE_READ;
159 b227a8e9 j_mayer
            break;
160 b227a8e9 j_mayer
        case 0x2:
161 b227a8e9 j_mayer
            access = PAGE_READ | PAGE_WRITE;
162 b227a8e9 j_mayer
            break;
163 b227a8e9 j_mayer
        }
164 b227a8e9 j_mayer
    }
165 b227a8e9 j_mayer
    if (nx == 0)
166 b227a8e9 j_mayer
        access |= PAGE_EXEC;
167 b227a8e9 j_mayer
168 b227a8e9 j_mayer
    return access;
169 b227a8e9 j_mayer
}
170 b227a8e9 j_mayer
171 636aa200 Blue Swirl
static inline int check_prot(int prot, int rw, int access_type)
172 b227a8e9 j_mayer
{
173 b227a8e9 j_mayer
    int ret;
174 b227a8e9 j_mayer
175 b227a8e9 j_mayer
    if (access_type == ACCESS_CODE) {
176 b227a8e9 j_mayer
        if (prot & PAGE_EXEC)
177 b227a8e9 j_mayer
            ret = 0;
178 b227a8e9 j_mayer
        else
179 b227a8e9 j_mayer
            ret = -2;
180 b227a8e9 j_mayer
    } else if (rw) {
181 b227a8e9 j_mayer
        if (prot & PAGE_WRITE)
182 b227a8e9 j_mayer
            ret = 0;
183 b227a8e9 j_mayer
        else
184 b227a8e9 j_mayer
            ret = -2;
185 b227a8e9 j_mayer
    } else {
186 b227a8e9 j_mayer
        if (prot & PAGE_READ)
187 b227a8e9 j_mayer
            ret = 0;
188 b227a8e9 j_mayer
        else
189 b227a8e9 j_mayer
            ret = -2;
190 b227a8e9 j_mayer
    }
191 b227a8e9 j_mayer
192 b227a8e9 j_mayer
    return ret;
193 b227a8e9 j_mayer
}
194 b227a8e9 j_mayer
195 c227f099 Anthony Liguori
static inline int _pte_check(mmu_ctx_t *ctx, int is_64b, target_ulong pte0,
196 636aa200 Blue Swirl
                             target_ulong pte1, int h, int rw, int type)
197 76a66253 j_mayer
{
198 caa4039c j_mayer
    target_ulong ptem, mmask;
199 b227a8e9 j_mayer
    int access, ret, pteh, ptev, pp;
200 76a66253 j_mayer
201 76a66253 j_mayer
    ret = -1;
202 76a66253 j_mayer
    /* Check validity and table match */
203 caa4039c j_mayer
#if defined(TARGET_PPC64)
204 caa4039c j_mayer
    if (is_64b) {
205 caa4039c j_mayer
        ptev = pte64_is_valid(pte0);
206 caa4039c j_mayer
        pteh = (pte0 >> 1) & 1;
207 caa4039c j_mayer
    } else
208 caa4039c j_mayer
#endif
209 caa4039c j_mayer
    {
210 caa4039c j_mayer
        ptev = pte_is_valid(pte0);
211 caa4039c j_mayer
        pteh = (pte0 >> 6) & 1;
212 caa4039c j_mayer
    }
213 caa4039c j_mayer
    if (ptev && h == pteh) {
214 76a66253 j_mayer
        /* Check vsid & api */
215 caa4039c j_mayer
#if defined(TARGET_PPC64)
216 caa4039c j_mayer
        if (is_64b) {
217 caa4039c j_mayer
            ptem = pte0 & PTE64_PTEM_MASK;
218 caa4039c j_mayer
            mmask = PTE64_CHECK_MASK;
219 b227a8e9 j_mayer
            pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
220 29c8ca6f blueswir1
            ctx->nx  = (pte1 >> 2) & 1; /* No execute bit */
221 b227a8e9 j_mayer
            ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
222 caa4039c j_mayer
        } else
223 caa4039c j_mayer
#endif
224 caa4039c j_mayer
        {
225 caa4039c j_mayer
            ptem = pte0 & PTE_PTEM_MASK;
226 caa4039c j_mayer
            mmask = PTE_CHECK_MASK;
227 b227a8e9 j_mayer
            pp = pte1 & 0x00000003;
228 caa4039c j_mayer
        }
229 caa4039c j_mayer
        if (ptem == ctx->ptem) {
230 c227f099 Anthony Liguori
            if (ctx->raddr != (target_phys_addr_t)-1ULL) {
231 76a66253 j_mayer
                /* all matches should have equal RPN, WIMG & PP */
232 caa4039c j_mayer
                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
233 93fcfe39 aliguori
                    qemu_log("Bad RPN/WIMG/PP\n");
234 76a66253 j_mayer
                    return -3;
235 76a66253 j_mayer
                }
236 76a66253 j_mayer
            }
237 76a66253 j_mayer
            /* Compute access rights */
238 b227a8e9 j_mayer
            access = pp_check(ctx->key, pp, ctx->nx);
239 76a66253 j_mayer
            /* Keep the matching PTE informations */
240 76a66253 j_mayer
            ctx->raddr = pte1;
241 76a66253 j_mayer
            ctx->prot = access;
242 b227a8e9 j_mayer
            ret = check_prot(ctx->prot, rw, type);
243 b227a8e9 j_mayer
            if (ret == 0) {
244 76a66253 j_mayer
                /* Access granted */
245 d12d51d5 aliguori
                LOG_MMU("PTE access granted !\n");
246 76a66253 j_mayer
            } else {
247 76a66253 j_mayer
                /* Access right violation */
248 d12d51d5 aliguori
                LOG_MMU("PTE access rejected\n");
249 76a66253 j_mayer
            }
250 76a66253 j_mayer
        }
251 76a66253 j_mayer
    }
252 76a66253 j_mayer
253 76a66253 j_mayer
    return ret;
254 76a66253 j_mayer
}
255 76a66253 j_mayer
256 c227f099 Anthony Liguori
static inline int pte32_check(mmu_ctx_t *ctx, target_ulong pte0,
257 636aa200 Blue Swirl
                              target_ulong pte1, int h, int rw, int type)
258 caa4039c j_mayer
{
259 b227a8e9 j_mayer
    return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
260 caa4039c j_mayer
}
261 caa4039c j_mayer
262 caa4039c j_mayer
#if defined(TARGET_PPC64)
263 c227f099 Anthony Liguori
static inline int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
264 636aa200 Blue Swirl
                              target_ulong pte1, int h, int rw, int type)
265 caa4039c j_mayer
{
266 b227a8e9 j_mayer
    return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
267 caa4039c j_mayer
}
268 caa4039c j_mayer
#endif
269 caa4039c j_mayer
270 c227f099 Anthony Liguori
static inline int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
271 636aa200 Blue Swirl
                                   int ret, int rw)
272 76a66253 j_mayer
{
273 76a66253 j_mayer
    int store = 0;
274 76a66253 j_mayer
275 76a66253 j_mayer
    /* Update page flags */
276 76a66253 j_mayer
    if (!(*pte1p & 0x00000100)) {
277 76a66253 j_mayer
        /* Update accessed flag */
278 76a66253 j_mayer
        *pte1p |= 0x00000100;
279 76a66253 j_mayer
        store = 1;
280 76a66253 j_mayer
    }
281 76a66253 j_mayer
    if (!(*pte1p & 0x00000080)) {
282 76a66253 j_mayer
        if (rw == 1 && ret == 0) {
283 76a66253 j_mayer
            /* Update changed flag */
284 76a66253 j_mayer
            *pte1p |= 0x00000080;
285 76a66253 j_mayer
            store = 1;
286 76a66253 j_mayer
        } else {
287 76a66253 j_mayer
            /* Force page fault for first write access */
288 76a66253 j_mayer
            ctx->prot &= ~PAGE_WRITE;
289 76a66253 j_mayer
        }
290 76a66253 j_mayer
    }
291 76a66253 j_mayer
292 76a66253 j_mayer
    return store;
293 76a66253 j_mayer
}
294 76a66253 j_mayer
295 76a66253 j_mayer
/* Software driven TLB helpers */
296 636aa200 Blue Swirl
static inline int ppc6xx_tlb_getnum(CPUState *env, target_ulong eaddr, int way,
297 636aa200 Blue Swirl
                                    int is_code)
298 76a66253 j_mayer
{
299 76a66253 j_mayer
    int nr;
300 76a66253 j_mayer
301 76a66253 j_mayer
    /* Select TLB num in a way from address */
302 76a66253 j_mayer
    nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
303 76a66253 j_mayer
    /* Select TLB way */
304 76a66253 j_mayer
    nr += env->tlb_per_way * way;
305 76a66253 j_mayer
    /* 6xx have separate TLBs for instructions and data */
306 76a66253 j_mayer
    if (is_code && env->id_tlbs == 1)
307 76a66253 j_mayer
        nr += env->nb_tlb;
308 76a66253 j_mayer
309 76a66253 j_mayer
    return nr;
310 76a66253 j_mayer
}
311 76a66253 j_mayer
312 636aa200 Blue Swirl
static inline void ppc6xx_tlb_invalidate_all(CPUState *env)
313 76a66253 j_mayer
{
314 c227f099 Anthony Liguori
    ppc6xx_tlb_t *tlb;
315 76a66253 j_mayer
    int nr, max;
316 76a66253 j_mayer
317 d12d51d5 aliguori
    //LOG_SWTLB("Invalidate all TLBs\n");
318 76a66253 j_mayer
    /* Invalidate all defined software TLB */
319 76a66253 j_mayer
    max = env->nb_tlb;
320 76a66253 j_mayer
    if (env->id_tlbs == 1)
321 76a66253 j_mayer
        max *= 2;
322 76a66253 j_mayer
    for (nr = 0; nr < max; nr++) {
323 1d0a48fb j_mayer
        tlb = &env->tlb[nr].tlb6;
324 76a66253 j_mayer
        pte_invalidate(&tlb->pte0);
325 76a66253 j_mayer
    }
326 76a66253 j_mayer
    tlb_flush(env, 1);
327 76a66253 j_mayer
}
328 76a66253 j_mayer
329 636aa200 Blue Swirl
static inline void __ppc6xx_tlb_invalidate_virt(CPUState *env,
330 636aa200 Blue Swirl
                                                target_ulong eaddr,
331 636aa200 Blue Swirl
                                                int is_code, int match_epn)
332 76a66253 j_mayer
{
333 4a057712 j_mayer
#if !defined(FLUSH_ALL_TLBS)
334 c227f099 Anthony Liguori
    ppc6xx_tlb_t *tlb;
335 76a66253 j_mayer
    int way, nr;
336 76a66253 j_mayer
337 76a66253 j_mayer
    /* Invalidate ITLB + DTLB, all ways */
338 76a66253 j_mayer
    for (way = 0; way < env->nb_ways; way++) {
339 76a66253 j_mayer
        nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
340 1d0a48fb j_mayer
        tlb = &env->tlb[nr].tlb6;
341 76a66253 j_mayer
        if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
342 90e189ec Blue Swirl
            LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
343 90e189ec Blue Swirl
                      env->nb_tlb, eaddr);
344 76a66253 j_mayer
            pte_invalidate(&tlb->pte0);
345 76a66253 j_mayer
            tlb_flush_page(env, tlb->EPN);
346 76a66253 j_mayer
        }
347 76a66253 j_mayer
    }
348 76a66253 j_mayer
#else
349 76a66253 j_mayer
    /* XXX: PowerPC specification say this is valid as well */
350 76a66253 j_mayer
    ppc6xx_tlb_invalidate_all(env);
351 76a66253 j_mayer
#endif
352 76a66253 j_mayer
}
353 76a66253 j_mayer
354 636aa200 Blue Swirl
static inline void ppc6xx_tlb_invalidate_virt(CPUState *env,
355 636aa200 Blue Swirl
                                              target_ulong eaddr, int is_code)
356 76a66253 j_mayer
{
357 76a66253 j_mayer
    __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
358 76a66253 j_mayer
}
359 76a66253 j_mayer
360 76a66253 j_mayer
void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
361 76a66253 j_mayer
                       target_ulong pte0, target_ulong pte1)
362 76a66253 j_mayer
{
363 c227f099 Anthony Liguori
    ppc6xx_tlb_t *tlb;
364 76a66253 j_mayer
    int nr;
365 76a66253 j_mayer
366 76a66253 j_mayer
    nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
367 1d0a48fb j_mayer
    tlb = &env->tlb[nr].tlb6;
368 90e189ec Blue Swirl
    LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
369 90e189ec Blue Swirl
              " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
370 76a66253 j_mayer
    /* Invalidate any pending reference in Qemu for this virtual address */
371 76a66253 j_mayer
    __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
372 76a66253 j_mayer
    tlb->pte0 = pte0;
373 76a66253 j_mayer
    tlb->pte1 = pte1;
374 76a66253 j_mayer
    tlb->EPN = EPN;
375 76a66253 j_mayer
    /* Store last way for LRU mechanism */
376 76a66253 j_mayer
    env->last_way = way;
377 76a66253 j_mayer
}
378 76a66253 j_mayer
379 c227f099 Anthony Liguori
static inline int ppc6xx_tlb_check(CPUState *env, mmu_ctx_t *ctx,
380 636aa200 Blue Swirl
                                   target_ulong eaddr, int rw, int access_type)
381 76a66253 j_mayer
{
382 c227f099 Anthony Liguori
    ppc6xx_tlb_t *tlb;
383 76a66253 j_mayer
    int nr, best, way;
384 76a66253 j_mayer
    int ret;
385 d9bce9d9 j_mayer
386 76a66253 j_mayer
    best = -1;
387 76a66253 j_mayer
    ret = -1; /* No TLB found */
388 76a66253 j_mayer
    for (way = 0; way < env->nb_ways; way++) {
389 76a66253 j_mayer
        nr = ppc6xx_tlb_getnum(env, eaddr, way,
390 76a66253 j_mayer
                               access_type == ACCESS_CODE ? 1 : 0);
391 1d0a48fb j_mayer
        tlb = &env->tlb[nr].tlb6;
392 76a66253 j_mayer
        /* This test "emulates" the PTE index match for hardware TLBs */
393 76a66253 j_mayer
        if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
394 90e189ec Blue Swirl
            LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
395 90e189ec Blue Swirl
                      "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb,
396 90e189ec Blue Swirl
                      pte_is_valid(tlb->pte0) ? "valid" : "inval",
397 90e189ec Blue Swirl
                      tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
398 76a66253 j_mayer
            continue;
399 76a66253 j_mayer
        }
400 90e189ec Blue Swirl
        LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " "
401 90e189ec Blue Swirl
                  TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb,
402 90e189ec Blue Swirl
                  pte_is_valid(tlb->pte0) ? "valid" : "inval",
403 90e189ec Blue Swirl
                  tlb->EPN, eaddr, tlb->pte1,
404 90e189ec Blue Swirl
                  rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
405 b227a8e9 j_mayer
        switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
406 76a66253 j_mayer
        case -3:
407 76a66253 j_mayer
            /* TLB inconsistency */
408 76a66253 j_mayer
            return -1;
409 76a66253 j_mayer
        case -2:
410 76a66253 j_mayer
            /* Access violation */
411 76a66253 j_mayer
            ret = -2;
412 76a66253 j_mayer
            best = nr;
413 76a66253 j_mayer
            break;
414 76a66253 j_mayer
        case -1:
415 76a66253 j_mayer
        default:
416 76a66253 j_mayer
            /* No match */
417 76a66253 j_mayer
            break;
418 76a66253 j_mayer
        case 0:
419 76a66253 j_mayer
            /* access granted */
420 76a66253 j_mayer
            /* XXX: we should go on looping to check all TLBs consistency
421 76a66253 j_mayer
             *      but we can speed-up the whole thing as the
422 76a66253 j_mayer
             *      result would be undefined if TLBs are not consistent.
423 76a66253 j_mayer
             */
424 76a66253 j_mayer
            ret = 0;
425 76a66253 j_mayer
            best = nr;
426 76a66253 j_mayer
            goto done;
427 76a66253 j_mayer
        }
428 76a66253 j_mayer
    }
429 76a66253 j_mayer
    if (best != -1) {
430 76a66253 j_mayer
    done:
431 90e189ec Blue Swirl
        LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
432 90e189ec Blue Swirl
                  ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
433 76a66253 j_mayer
        /* Update page flags */
434 1d0a48fb j_mayer
        pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
435 76a66253 j_mayer
    }
436 76a66253 j_mayer
437 76a66253 j_mayer
    return ret;
438 76a66253 j_mayer
}
439 76a66253 j_mayer
440 9a64fbe4 bellard
/* Perform BAT hit & translation */
441 636aa200 Blue Swirl
static inline void bat_size_prot(CPUState *env, target_ulong *blp, int *validp,
442 636aa200 Blue Swirl
                                 int *protp, target_ulong *BATu,
443 636aa200 Blue Swirl
                                 target_ulong *BATl)
444 faadf50e j_mayer
{
445 faadf50e j_mayer
    target_ulong bl;
446 faadf50e j_mayer
    int pp, valid, prot;
447 faadf50e j_mayer
448 faadf50e j_mayer
    bl = (*BATu & 0x00001FFC) << 15;
449 faadf50e j_mayer
    valid = 0;
450 faadf50e j_mayer
    prot = 0;
451 faadf50e j_mayer
    if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
452 faadf50e j_mayer
        ((msr_pr != 0) && (*BATu & 0x00000001))) {
453 faadf50e j_mayer
        valid = 1;
454 faadf50e j_mayer
        pp = *BATl & 0x00000003;
455 faadf50e j_mayer
        if (pp != 0) {
456 faadf50e j_mayer
            prot = PAGE_READ | PAGE_EXEC;
457 faadf50e j_mayer
            if (pp == 0x2)
458 faadf50e j_mayer
                prot |= PAGE_WRITE;
459 faadf50e j_mayer
        }
460 faadf50e j_mayer
    }
461 faadf50e j_mayer
    *blp = bl;
462 faadf50e j_mayer
    *validp = valid;
463 faadf50e j_mayer
    *protp = prot;
464 faadf50e j_mayer
}
465 faadf50e j_mayer
466 636aa200 Blue Swirl
static inline void bat_601_size_prot(CPUState *env, target_ulong *blp,
467 636aa200 Blue Swirl
                                     int *validp, int *protp,
468 636aa200 Blue Swirl
                                     target_ulong *BATu, target_ulong *BATl)
469 faadf50e j_mayer
{
470 faadf50e j_mayer
    target_ulong bl;
471 faadf50e j_mayer
    int key, pp, valid, prot;
472 faadf50e j_mayer
473 faadf50e j_mayer
    bl = (*BATl & 0x0000003F) << 17;
474 90e189ec Blue Swirl
    LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
475 90e189ec Blue Swirl
             (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
476 faadf50e j_mayer
    prot = 0;
477 faadf50e j_mayer
    valid = (*BATl >> 6) & 1;
478 faadf50e j_mayer
    if (valid) {
479 faadf50e j_mayer
        pp = *BATu & 0x00000003;
480 faadf50e j_mayer
        if (msr_pr == 0)
481 faadf50e j_mayer
            key = (*BATu >> 3) & 1;
482 faadf50e j_mayer
        else
483 faadf50e j_mayer
            key = (*BATu >> 2) & 1;
484 faadf50e j_mayer
        prot = pp_check(key, pp, 0);
485 faadf50e j_mayer
    }
486 faadf50e j_mayer
    *blp = bl;
487 faadf50e j_mayer
    *validp = valid;
488 faadf50e j_mayer
    *protp = prot;
489 faadf50e j_mayer
}
490 faadf50e j_mayer
491 c227f099 Anthony Liguori
static inline int get_bat(CPUState *env, mmu_ctx_t *ctx, target_ulong virtual,
492 636aa200 Blue Swirl
                          int rw, int type)
493 9a64fbe4 bellard
{
494 76a66253 j_mayer
    target_ulong *BATlt, *BATut, *BATu, *BATl;
495 05f92404 Blue Swirl
    target_ulong BEPIl, BEPIu, bl;
496 faadf50e j_mayer
    int i, valid, prot;
497 9a64fbe4 bellard
    int ret = -1;
498 9a64fbe4 bellard
499 90e189ec Blue Swirl
    LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
500 90e189ec Blue Swirl
             type == ACCESS_CODE ? 'I' : 'D', virtual);
501 9a64fbe4 bellard
    switch (type) {
502 9a64fbe4 bellard
    case ACCESS_CODE:
503 9a64fbe4 bellard
        BATlt = env->IBAT[1];
504 9a64fbe4 bellard
        BATut = env->IBAT[0];
505 9a64fbe4 bellard
        break;
506 9a64fbe4 bellard
    default:
507 9a64fbe4 bellard
        BATlt = env->DBAT[1];
508 9a64fbe4 bellard
        BATut = env->DBAT[0];
509 9a64fbe4 bellard
        break;
510 9a64fbe4 bellard
    }
511 faadf50e j_mayer
    for (i = 0; i < env->nb_BATs; i++) {
512 9a64fbe4 bellard
        BATu = &BATut[i];
513 9a64fbe4 bellard
        BATl = &BATlt[i];
514 9a64fbe4 bellard
        BEPIu = *BATu & 0xF0000000;
515 9a64fbe4 bellard
        BEPIl = *BATu & 0x0FFE0000;
516 faadf50e j_mayer
        if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
517 faadf50e j_mayer
            bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
518 faadf50e j_mayer
        } else {
519 faadf50e j_mayer
            bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
520 faadf50e j_mayer
        }
521 90e189ec Blue Swirl
        LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
522 90e189ec Blue Swirl
                 " BATl " TARGET_FMT_lx "\n", __func__,
523 90e189ec Blue Swirl
                 type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
524 9a64fbe4 bellard
        if ((virtual & 0xF0000000) == BEPIu &&
525 9a64fbe4 bellard
            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
526 9a64fbe4 bellard
            /* BAT matches */
527 faadf50e j_mayer
            if (valid != 0) {
528 9a64fbe4 bellard
                /* Get physical address */
529 76a66253 j_mayer
                ctx->raddr = (*BATl & 0xF0000000) |
530 9a64fbe4 bellard
                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
531 a541f297 bellard
                    (virtual & 0x0001F000);
532 b227a8e9 j_mayer
                /* Compute access rights */
533 faadf50e j_mayer
                ctx->prot = prot;
534 b227a8e9 j_mayer
                ret = check_prot(ctx->prot, rw, type);
535 d12d51d5 aliguori
                if (ret == 0)
536 90e189ec Blue Swirl
                    LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
537 d12d51d5 aliguori
                             i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
538 d12d51d5 aliguori
                             ctx->prot & PAGE_WRITE ? 'W' : '-');
539 9a64fbe4 bellard
                break;
540 9a64fbe4 bellard
            }
541 9a64fbe4 bellard
        }
542 9a64fbe4 bellard
    }
543 9a64fbe4 bellard
    if (ret < 0) {
544 d12d51d5 aliguori
#if defined(DEBUG_BATS)
545 0bf9e31a Blue Swirl
        if (qemu_log_enabled()) {
546 90e189ec Blue Swirl
            LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
547 4a057712 j_mayer
            for (i = 0; i < 4; i++) {
548 4a057712 j_mayer
                BATu = &BATut[i];
549 4a057712 j_mayer
                BATl = &BATlt[i];
550 4a057712 j_mayer
                BEPIu = *BATu & 0xF0000000;
551 4a057712 j_mayer
                BEPIl = *BATu & 0x0FFE0000;
552 4a057712 j_mayer
                bl = (*BATu & 0x00001FFC) << 15;
553 90e189ec Blue Swirl
                LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
554 90e189ec Blue Swirl
                         " BATl " TARGET_FMT_lx " \n\t" TARGET_FMT_lx " "
555 90e189ec Blue Swirl
                         TARGET_FMT_lx " " TARGET_FMT_lx "\n",
556 0bf9e31a Blue Swirl
                         __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
557 0bf9e31a Blue Swirl
                         *BATu, *BATl, BEPIu, BEPIl, bl);
558 4a057712 j_mayer
            }
559 9a64fbe4 bellard
        }
560 9a64fbe4 bellard
#endif
561 9a64fbe4 bellard
    }
562 9a64fbe4 bellard
    /* No hit */
563 9a64fbe4 bellard
    return ret;
564 9a64fbe4 bellard
}
565 9a64fbe4 bellard
566 9a64fbe4 bellard
/* PTE table lookup */
567 c227f099 Anthony Liguori
static inline int _find_pte(mmu_ctx_t *ctx, int is_64b, int h, int rw,
568 636aa200 Blue Swirl
                            int type, int target_page_bits)
569 9a64fbe4 bellard
{
570 76a66253 j_mayer
    target_ulong base, pte0, pte1;
571 76a66253 j_mayer
    int i, good = -1;
572 caa4039c j_mayer
    int ret, r;
573 9a64fbe4 bellard
574 76a66253 j_mayer
    ret = -1; /* No entry found */
575 76a66253 j_mayer
    base = ctx->pg_addr[h];
576 9a64fbe4 bellard
    for (i = 0; i < 8; i++) {
577 caa4039c j_mayer
#if defined(TARGET_PPC64)
578 caa4039c j_mayer
        if (is_64b) {
579 caa4039c j_mayer
            pte0 = ldq_phys(base + (i * 16));
580 5b5aba4f blueswir1
            pte1 = ldq_phys(base + (i * 16) + 8);
581 5b5aba4f blueswir1
582 5b5aba4f blueswir1
            /* We have a TLB that saves 4K pages, so let's
583 5b5aba4f blueswir1
             * split a huge page to 4k chunks */
584 5b5aba4f blueswir1
            if (target_page_bits != TARGET_PAGE_BITS)
585 5b5aba4f blueswir1
                pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1))
586 5b5aba4f blueswir1
                        & TARGET_PAGE_MASK;
587 5b5aba4f blueswir1
588 b227a8e9 j_mayer
            r = pte64_check(ctx, pte0, pte1, h, rw, type);
589 90e189ec Blue Swirl
            LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
590 90e189ec Blue Swirl
                    TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
591 90e189ec Blue Swirl
                    base + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
592 90e189ec Blue Swirl
                    (int)((pte0 >> 1) & 1), ctx->ptem);
593 caa4039c j_mayer
        } else
594 caa4039c j_mayer
#endif
595 caa4039c j_mayer
        {
596 caa4039c j_mayer
            pte0 = ldl_phys(base + (i * 8));
597 caa4039c j_mayer
            pte1 =  ldl_phys(base + (i * 8) + 4);
598 b227a8e9 j_mayer
            r = pte32_check(ctx, pte0, pte1, h, rw, type);
599 90e189ec Blue Swirl
            LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
600 90e189ec Blue Swirl
                    TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
601 90e189ec Blue Swirl
                    base + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
602 90e189ec Blue Swirl
                    (int)((pte0 >> 6) & 1), ctx->ptem);
603 12de9a39 j_mayer
        }
604 caa4039c j_mayer
        switch (r) {
605 76a66253 j_mayer
        case -3:
606 76a66253 j_mayer
            /* PTE inconsistency */
607 76a66253 j_mayer
            return -1;
608 76a66253 j_mayer
        case -2:
609 76a66253 j_mayer
            /* Access violation */
610 76a66253 j_mayer
            ret = -2;
611 76a66253 j_mayer
            good = i;
612 76a66253 j_mayer
            break;
613 76a66253 j_mayer
        case -1:
614 76a66253 j_mayer
        default:
615 76a66253 j_mayer
            /* No PTE match */
616 76a66253 j_mayer
            break;
617 76a66253 j_mayer
        case 0:
618 76a66253 j_mayer
            /* access granted */
619 76a66253 j_mayer
            /* XXX: we should go on looping to check all PTEs consistency
620 76a66253 j_mayer
             *      but if we can speed-up the whole thing as the
621 76a66253 j_mayer
             *      result would be undefined if PTEs are not consistent.
622 76a66253 j_mayer
             */
623 76a66253 j_mayer
            ret = 0;
624 76a66253 j_mayer
            good = i;
625 76a66253 j_mayer
            goto done;
626 9a64fbe4 bellard
        }
627 9a64fbe4 bellard
    }
628 9a64fbe4 bellard
    if (good != -1) {
629 76a66253 j_mayer
    done:
630 90e189ec Blue Swirl
        LOG_MMU("found PTE at addr " TARGET_FMT_lx " prot=%01x ret=%d\n",
631 90e189ec Blue Swirl
                ctx->raddr, ctx->prot, ret);
632 9a64fbe4 bellard
        /* Update page flags */
633 76a66253 j_mayer
        pte1 = ctx->raddr;
634 caa4039c j_mayer
        if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
635 caa4039c j_mayer
#if defined(TARGET_PPC64)
636 caa4039c j_mayer
            if (is_64b) {
637 caa4039c j_mayer
                stq_phys_notdirty(base + (good * 16) + 8, pte1);
638 caa4039c j_mayer
            } else
639 caa4039c j_mayer
#endif
640 caa4039c j_mayer
            {
641 caa4039c j_mayer
                stl_phys_notdirty(base + (good * 8) + 4, pte1);
642 caa4039c j_mayer
            }
643 caa4039c j_mayer
        }
644 9a64fbe4 bellard
    }
645 9a64fbe4 bellard
646 9a64fbe4 bellard
    return ret;
647 79aceca5 bellard
}
648 79aceca5 bellard
649 c227f099 Anthony Liguori
static inline int find_pte32(mmu_ctx_t *ctx, int h, int rw, int type,
650 636aa200 Blue Swirl
                             int target_page_bits)
651 caa4039c j_mayer
{
652 5b5aba4f blueswir1
    return _find_pte(ctx, 0, h, rw, type, target_page_bits);
653 caa4039c j_mayer
}
654 caa4039c j_mayer
655 caa4039c j_mayer
#if defined(TARGET_PPC64)
656 c227f099 Anthony Liguori
static inline int find_pte64(mmu_ctx_t *ctx, int h, int rw, int type,
657 636aa200 Blue Swirl
                             int target_page_bits)
658 caa4039c j_mayer
{
659 5b5aba4f blueswir1
    return _find_pte(ctx, 1, h, rw, type, target_page_bits);
660 caa4039c j_mayer
}
661 caa4039c j_mayer
#endif
662 caa4039c j_mayer
663 c227f099 Anthony Liguori
static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
664 636aa200 Blue Swirl
                           int type, int target_page_bits)
665 caa4039c j_mayer
{
666 caa4039c j_mayer
#if defined(TARGET_PPC64)
667 add78955 j_mayer
    if (env->mmu_model & POWERPC_MMU_64)
668 5b5aba4f blueswir1
        return find_pte64(ctx, h, rw, type, target_page_bits);
669 caa4039c j_mayer
#endif
670 caa4039c j_mayer
671 5b5aba4f blueswir1
    return find_pte32(ctx, h, rw, type, target_page_bits);
672 caa4039c j_mayer
}
673 caa4039c j_mayer
674 caa4039c j_mayer
#if defined(TARGET_PPC64)
675 c227f099 Anthony Liguori
static ppc_slb_t *slb_get_entry(CPUPPCState *env, int nr)
676 eacc3249 j_mayer
{
677 c227f099 Anthony Liguori
    ppc_slb_t *retval = &env->slb[nr];
678 8eee0af9 blueswir1
679 8eee0af9 blueswir1
#if 0 // XXX implement bridge mode?
680 8eee0af9 blueswir1
    if (env->spr[SPR_ASR] & 1) {
681 c227f099 Anthony Liguori
        target_phys_addr_t sr_base;
682 8eee0af9 blueswir1

683 8eee0af9 blueswir1
        sr_base = env->spr[SPR_ASR] & 0xfffffffffffff000;
684 8eee0af9 blueswir1
        sr_base += (12 * nr);
685 8eee0af9 blueswir1

686 8eee0af9 blueswir1
        retval->tmp64 = ldq_phys(sr_base);
687 8eee0af9 blueswir1
        retval->tmp = ldl_phys(sr_base + 8);
688 8eee0af9 blueswir1
    }
689 8eee0af9 blueswir1
#endif
690 8eee0af9 blueswir1
691 8eee0af9 blueswir1
    return retval;
692 eacc3249 j_mayer
}
693 eacc3249 j_mayer
694 c227f099 Anthony Liguori
static void slb_set_entry(CPUPPCState *env, int nr, ppc_slb_t *slb)
695 eacc3249 j_mayer
{
696 c227f099 Anthony Liguori
    ppc_slb_t *entry = &env->slb[nr];
697 8eee0af9 blueswir1
698 8eee0af9 blueswir1
    if (slb == entry)
699 8eee0af9 blueswir1
        return;
700 8eee0af9 blueswir1
701 8eee0af9 blueswir1
    entry->tmp64 = slb->tmp64;
702 8eee0af9 blueswir1
    entry->tmp = slb->tmp;
703 8eee0af9 blueswir1
}
704 8eee0af9 blueswir1
705 c227f099 Anthony Liguori
static inline int slb_is_valid(ppc_slb_t *slb)
706 8eee0af9 blueswir1
{
707 8eee0af9 blueswir1
    return (int)(slb->tmp64 & 0x0000000008000000ULL);
708 8eee0af9 blueswir1
}
709 8eee0af9 blueswir1
710 c227f099 Anthony Liguori
static inline void slb_invalidate(ppc_slb_t *slb)
711 8eee0af9 blueswir1
{
712 8eee0af9 blueswir1
    slb->tmp64 &= ~0x0000000008000000ULL;
713 eacc3249 j_mayer
}
714 eacc3249 j_mayer
715 636aa200 Blue Swirl
static inline int slb_lookup(CPUPPCState *env, target_ulong eaddr,
716 636aa200 Blue Swirl
                             target_ulong *vsid, target_ulong *page_mask,
717 636aa200 Blue Swirl
                             int *attr, int *target_page_bits)
718 caa4039c j_mayer
{
719 caa4039c j_mayer
    target_ulong mask;
720 caa4039c j_mayer
    int n, ret;
721 caa4039c j_mayer
722 caa4039c j_mayer
    ret = -5;
723 90e189ec Blue Swirl
    LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
724 caa4039c j_mayer
    mask = 0x0000000000000000ULL; /* Avoid gcc warning */
725 eacc3249 j_mayer
    for (n = 0; n < env->slb_nr; n++) {
726 c227f099 Anthony Liguori
        ppc_slb_t *slb = slb_get_entry(env, n);
727 8eee0af9 blueswir1
728 8eee0af9 blueswir1
        LOG_SLB("%s: seg %d %016" PRIx64 " %08"
729 8eee0af9 blueswir1
                    PRIx32 "\n", __func__, n, slb->tmp64, slb->tmp);
730 8eee0af9 blueswir1
        if (slb_is_valid(slb)) {
731 caa4039c j_mayer
            /* SLB entry is valid */
732 b2eca445 Alexander Graf
            mask = 0xFFFFFFFFF0000000ULL;
733 8eee0af9 blueswir1
            if (slb->tmp & 0x8) {
734 b2eca445 Alexander Graf
                /* 16 MB PTEs */
735 5b5aba4f blueswir1
                if (target_page_bits)
736 b2eca445 Alexander Graf
                    *target_page_bits = 24;
737 5b5aba4f blueswir1
            } else {
738 b2eca445 Alexander Graf
                /* 4 KB PTEs */
739 5b5aba4f blueswir1
                if (target_page_bits)
740 5b5aba4f blueswir1
                    *target_page_bits = TARGET_PAGE_BITS;
741 caa4039c j_mayer
            }
742 8eee0af9 blueswir1
            if ((eaddr & mask) == (slb->tmp64 & mask)) {
743 caa4039c j_mayer
                /* SLB match */
744 8eee0af9 blueswir1
                *vsid = ((slb->tmp64 << 24) | (slb->tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
745 caa4039c j_mayer
                *page_mask = ~mask;
746 8eee0af9 blueswir1
                *attr = slb->tmp & 0xFF;
747 eacc3249 j_mayer
                ret = n;
748 caa4039c j_mayer
                break;
749 caa4039c j_mayer
            }
750 caa4039c j_mayer
        }
751 caa4039c j_mayer
    }
752 caa4039c j_mayer
753 caa4039c j_mayer
    return ret;
754 79aceca5 bellard
}
755 12de9a39 j_mayer
756 eacc3249 j_mayer
void ppc_slb_invalidate_all (CPUPPCState *env)
757 eacc3249 j_mayer
{
758 eacc3249 j_mayer
    int n, do_invalidate;
759 eacc3249 j_mayer
760 eacc3249 j_mayer
    do_invalidate = 0;
761 2c1ee068 j_mayer
    /* XXX: Warning: slbia never invalidates the first segment */
762 2c1ee068 j_mayer
    for (n = 1; n < env->slb_nr; n++) {
763 c227f099 Anthony Liguori
        ppc_slb_t *slb = slb_get_entry(env, n);
764 8eee0af9 blueswir1
765 8eee0af9 blueswir1
        if (slb_is_valid(slb)) {
766 8eee0af9 blueswir1
            slb_invalidate(slb);
767 8eee0af9 blueswir1
            slb_set_entry(env, n, slb);
768 eacc3249 j_mayer
            /* XXX: given the fact that segment size is 256 MB or 1TB,
769 eacc3249 j_mayer
             *      and we still don't have a tlb_flush_mask(env, n, mask)
770 eacc3249 j_mayer
             *      in Qemu, we just invalidate all TLBs
771 eacc3249 j_mayer
             */
772 eacc3249 j_mayer
            do_invalidate = 1;
773 eacc3249 j_mayer
        }
774 eacc3249 j_mayer
    }
775 eacc3249 j_mayer
    if (do_invalidate)
776 eacc3249 j_mayer
        tlb_flush(env, 1);
777 eacc3249 j_mayer
}
778 eacc3249 j_mayer
779 eacc3249 j_mayer
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
780 eacc3249 j_mayer
{
781 eacc3249 j_mayer
    target_ulong vsid, page_mask;
782 eacc3249 j_mayer
    int attr;
783 eacc3249 j_mayer
    int n;
784 eacc3249 j_mayer
785 5b5aba4f blueswir1
    n = slb_lookup(env, T0, &vsid, &page_mask, &attr, NULL);
786 eacc3249 j_mayer
    if (n >= 0) {
787 c227f099 Anthony Liguori
        ppc_slb_t *slb = slb_get_entry(env, n);
788 8eee0af9 blueswir1
789 8eee0af9 blueswir1
        if (slb_is_valid(slb)) {
790 8eee0af9 blueswir1
            slb_invalidate(slb);
791 8eee0af9 blueswir1
            slb_set_entry(env, n, slb);
792 eacc3249 j_mayer
            /* XXX: given the fact that segment size is 256 MB or 1TB,
793 eacc3249 j_mayer
             *      and we still don't have a tlb_flush_mask(env, n, mask)
794 eacc3249 j_mayer
             *      in Qemu, we just invalidate all TLBs
795 eacc3249 j_mayer
             */
796 eacc3249 j_mayer
            tlb_flush(env, 1);
797 eacc3249 j_mayer
        }
798 eacc3249 j_mayer
    }
799 eacc3249 j_mayer
}
800 eacc3249 j_mayer
801 12de9a39 j_mayer
target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
802 12de9a39 j_mayer
{
803 12de9a39 j_mayer
    target_ulong rt;
804 c227f099 Anthony Liguori
    ppc_slb_t *slb = slb_get_entry(env, slb_nr);
805 8eee0af9 blueswir1
806 8eee0af9 blueswir1
    if (slb_is_valid(slb)) {
807 12de9a39 j_mayer
        /* SLB entry is valid */
808 12de9a39 j_mayer
        /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
809 8eee0af9 blueswir1
        rt = slb->tmp >> 8;             /* 65:88 => 40:63 */
810 8eee0af9 blueswir1
        rt |= (slb->tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
811 12de9a39 j_mayer
        /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
812 8eee0af9 blueswir1
        rt |= ((slb->tmp >> 4) & 0xF) << 27;
813 12de9a39 j_mayer
    } else {
814 12de9a39 j_mayer
        rt = 0;
815 12de9a39 j_mayer
    }
816 8eee0af9 blueswir1
    LOG_SLB("%s: %016" PRIx64 " %08" PRIx32 " => %d "
817 90e189ec Blue Swirl
            TARGET_FMT_lx "\n", __func__, slb->tmp64, slb->tmp, slb_nr, rt);
818 12de9a39 j_mayer
819 12de9a39 j_mayer
    return rt;
820 12de9a39 j_mayer
}
821 12de9a39 j_mayer
822 f6b868fc blueswir1
void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
823 12de9a39 j_mayer
{
824 c227f099 Anthony Liguori
    ppc_slb_t *slb;
825 12de9a39 j_mayer
826 f6b868fc blueswir1
    uint64_t vsid;
827 f6b868fc blueswir1
    uint64_t esid;
828 f6b868fc blueswir1
    int flags, valid, slb_nr;
829 f6b868fc blueswir1
830 f6b868fc blueswir1
    vsid = rs >> 12;
831 f6b868fc blueswir1
    flags = ((rs >> 8) & 0xf);
832 f6b868fc blueswir1
833 f6b868fc blueswir1
    esid = rb >> 28;
834 f6b868fc blueswir1
    valid = (rb & (1 << 27));
835 f6b868fc blueswir1
    slb_nr = rb & 0xfff;
836 f6b868fc blueswir1
837 8eee0af9 blueswir1
    slb = slb_get_entry(env, slb_nr);
838 8eee0af9 blueswir1
    slb->tmp64 = (esid << 28) | valid | (vsid >> 24);
839 8eee0af9 blueswir1
    slb->tmp = (vsid << 8) | (flags << 3);
840 f6b868fc blueswir1
841 90e189ec Blue Swirl
    LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
842 90e189ec Blue Swirl
            " %08" PRIx32 "\n", __func__, slb_nr, rb, rs, slb->tmp64,
843 90e189ec Blue Swirl
            slb->tmp);
844 f6b868fc blueswir1
845 8eee0af9 blueswir1
    slb_set_entry(env, slb_nr, slb);
846 12de9a39 j_mayer
}
847 caa4039c j_mayer
#endif /* defined(TARGET_PPC64) */
848 79aceca5 bellard
849 9a64fbe4 bellard
/* Perform segment based translation */
850 c227f099 Anthony Liguori
static inline target_phys_addr_t get_pgaddr(target_phys_addr_t sdr1,
851 636aa200 Blue Swirl
                                            int sdr_sh,
852 c227f099 Anthony Liguori
                                            target_phys_addr_t hash,
853 c227f099 Anthony Liguori
                                            target_phys_addr_t mask)
854 12de9a39 j_mayer
{
855 c227f099 Anthony Liguori
    return (sdr1 & ((target_phys_addr_t)(-1ULL) << sdr_sh)) | (hash & mask);
856 12de9a39 j_mayer
}
857 12de9a39 j_mayer
858 c227f099 Anthony Liguori
static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
859 636aa200 Blue Swirl
                              target_ulong eaddr, int rw, int type)
860 79aceca5 bellard
{
861 c227f099 Anthony Liguori
    target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
862 caa4039c j_mayer
    target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
863 caa4039c j_mayer
#if defined(TARGET_PPC64)
864 caa4039c j_mayer
    int attr;
865 9a64fbe4 bellard
#endif
866 5b5aba4f blueswir1
    int ds, vsid_sh, sdr_sh, pr, target_page_bits;
867 caa4039c j_mayer
    int ret, ret2;
868 caa4039c j_mayer
869 0411a972 j_mayer
    pr = msr_pr;
870 caa4039c j_mayer
#if defined(TARGET_PPC64)
871 add78955 j_mayer
    if (env->mmu_model & POWERPC_MMU_64) {
872 d12d51d5 aliguori
        LOG_MMU("Check SLBs\n");
873 5b5aba4f blueswir1
        ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr,
874 5b5aba4f blueswir1
                         &target_page_bits);
875 caa4039c j_mayer
        if (ret < 0)
876 caa4039c j_mayer
            return ret;
877 0411a972 j_mayer
        ctx->key = ((attr & 0x40) && (pr != 0)) ||
878 0411a972 j_mayer
            ((attr & 0x80) && (pr == 0)) ? 1 : 0;
879 caa4039c j_mayer
        ds = 0;
880 5b5aba4f blueswir1
        ctx->nx = attr & 0x10 ? 1 : 0;
881 5b5aba4f blueswir1
        ctx->eaddr = eaddr;
882 caa4039c j_mayer
        vsid_mask = 0x00003FFFFFFFFF80ULL;
883 caa4039c j_mayer
        vsid_sh = 7;
884 caa4039c j_mayer
        sdr_sh = 18;
885 caa4039c j_mayer
        sdr_mask = 0x3FF80;
886 caa4039c j_mayer
    } else
887 caa4039c j_mayer
#endif /* defined(TARGET_PPC64) */
888 caa4039c j_mayer
    {
889 caa4039c j_mayer
        sr = env->sr[eaddr >> 28];
890 caa4039c j_mayer
        page_mask = 0x0FFFFFFF;
891 0411a972 j_mayer
        ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
892 0411a972 j_mayer
                    ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
893 caa4039c j_mayer
        ds = sr & 0x80000000 ? 1 : 0;
894 b227a8e9 j_mayer
        ctx->nx = sr & 0x10000000 ? 1 : 0;
895 caa4039c j_mayer
        vsid = sr & 0x00FFFFFF;
896 caa4039c j_mayer
        vsid_mask = 0x01FFFFC0;
897 caa4039c j_mayer
        vsid_sh = 6;
898 caa4039c j_mayer
        sdr_sh = 16;
899 caa4039c j_mayer
        sdr_mask = 0xFFC0;
900 5b5aba4f blueswir1
        target_page_bits = TARGET_PAGE_BITS;
901 90e189ec Blue Swirl
        LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
902 90e189ec Blue Swirl
                TARGET_FMT_lx " lr=" TARGET_FMT_lx
903 90e189ec Blue Swirl
                " ir=%d dr=%d pr=%d %d t=%d\n",
904 90e189ec Blue Swirl
                eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
905 90e189ec Blue Swirl
                (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
906 caa4039c j_mayer
    }
907 90e189ec Blue Swirl
    LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
908 90e189ec Blue Swirl
            ctx->key, ds, ctx->nx, vsid);
909 caa4039c j_mayer
    ret = -1;
910 caa4039c j_mayer
    if (!ds) {
911 9a64fbe4 bellard
        /* Check if instruction fetch is allowed, if needed */
912 b227a8e9 j_mayer
        if (type != ACCESS_CODE || ctx->nx == 0) {
913 9a64fbe4 bellard
            /* Page address translation */
914 76a66253 j_mayer
            /* Primary table address */
915 76a66253 j_mayer
            sdr = env->sdr1;
916 5b5aba4f blueswir1
            pgidx = (eaddr & page_mask) >> target_page_bits;
917 12de9a39 j_mayer
#if defined(TARGET_PPC64)
918 add78955 j_mayer
            if (env->mmu_model & POWERPC_MMU_64) {
919 12de9a39 j_mayer
                htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
920 12de9a39 j_mayer
                /* XXX: this is false for 1 TB segments */
921 12de9a39 j_mayer
                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
922 12de9a39 j_mayer
            } else
923 12de9a39 j_mayer
#endif
924 12de9a39 j_mayer
            {
925 12de9a39 j_mayer
                htab_mask = sdr & 0x000001FF;
926 12de9a39 j_mayer
                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
927 12de9a39 j_mayer
            }
928 12de9a39 j_mayer
            mask = (htab_mask << sdr_sh) | sdr_mask;
929 90e189ec Blue Swirl
            LOG_MMU("sdr " TARGET_FMT_plx " sh %d hash " TARGET_FMT_plx
930 90e189ec Blue Swirl
                    " mask " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
931 90e189ec Blue Swirl
                    sdr, sdr_sh, hash, mask, page_mask);
932 caa4039c j_mayer
            ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask);
933 76a66253 j_mayer
            /* Secondary table address */
934 caa4039c j_mayer
            hash = (~hash) & vsid_mask;
935 90e189ec Blue Swirl
            LOG_MMU("sdr " TARGET_FMT_plx " sh %d hash " TARGET_FMT_plx
936 90e189ec Blue Swirl
                    " mask " TARGET_FMT_plx "\n", sdr, sdr_sh, hash, mask);
937 caa4039c j_mayer
            ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
938 caa4039c j_mayer
#if defined(TARGET_PPC64)
939 add78955 j_mayer
            if (env->mmu_model & POWERPC_MMU_64) {
940 caa4039c j_mayer
                /* Only 5 bits of the page index are used in the AVPN */
941 5b5aba4f blueswir1
                if (target_page_bits > 23) {
942 5b5aba4f blueswir1
                    ctx->ptem = (vsid << 12) |
943 5b5aba4f blueswir1
                                ((pgidx << (target_page_bits - 16)) & 0xF80);
944 5b5aba4f blueswir1
                } else {
945 5b5aba4f blueswir1
                    ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
946 5b5aba4f blueswir1
                }
947 caa4039c j_mayer
            } else
948 caa4039c j_mayer
#endif
949 caa4039c j_mayer
            {
950 caa4039c j_mayer
                ctx->ptem = (vsid << 7) | (pgidx >> 10);
951 caa4039c j_mayer
            }
952 76a66253 j_mayer
            /* Initialize real address with an invalid value */
953 c227f099 Anthony Liguori
            ctx->raddr = (target_phys_addr_t)-1ULL;
954 7dbe11ac j_mayer
            if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
955 7dbe11ac j_mayer
                         env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
956 76a66253 j_mayer
                /* Software TLB search */
957 76a66253 j_mayer
                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
958 76a66253 j_mayer
            } else {
959 90e189ec Blue Swirl
                LOG_MMU("0 sdr1=" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " "
960 90e189ec Blue Swirl
                        "api=" TARGET_FMT_lx " hash=" TARGET_FMT_plx
961 90e189ec Blue Swirl
                        " pg_addr=" TARGET_FMT_plx "\n",
962 90e189ec Blue Swirl
                        sdr, vsid, pgidx, hash, ctx->pg_addr[0]);
963 76a66253 j_mayer
                /* Primary table lookup */
964 5b5aba4f blueswir1
                ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
965 76a66253 j_mayer
                if (ret < 0) {
966 76a66253 j_mayer
                    /* Secondary table lookup */
967 d12d51d5 aliguori
                    if (eaddr != 0xEFFFFFFF)
968 90e189ec Blue Swirl
                        LOG_MMU("1 sdr1=" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " "
969 90e189ec Blue Swirl
                                "api=" TARGET_FMT_lx " hash=" TARGET_FMT_plx
970 90e189ec Blue Swirl
                                " pg_addr=" TARGET_FMT_plx "\n", sdr, vsid,
971 90e189ec Blue Swirl
                                pgidx, hash, ctx->pg_addr[1]);
972 5b5aba4f blueswir1
                    ret2 = find_pte(env, ctx, 1, rw, type,
973 5b5aba4f blueswir1
                                    target_page_bits);
974 76a66253 j_mayer
                    if (ret2 != -1)
975 76a66253 j_mayer
                        ret = ret2;
976 76a66253 j_mayer
                }
977 9a64fbe4 bellard
            }
978 0411a972 j_mayer
#if defined (DUMP_PAGE_TABLES)
979 93fcfe39 aliguori
            if (qemu_log_enabled()) {
980 c227f099 Anthony Liguori
                target_phys_addr_t curaddr;
981 b33c17e1 j_mayer
                uint32_t a0, a1, a2, a3;
982 90e189ec Blue Swirl
                qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
983 90e189ec Blue Swirl
                         "\n", sdr, mask + 0x80);
984 b33c17e1 j_mayer
                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
985 b33c17e1 j_mayer
                     curaddr += 16) {
986 b33c17e1 j_mayer
                    a0 = ldl_phys(curaddr);
987 b33c17e1 j_mayer
                    a1 = ldl_phys(curaddr + 4);
988 b33c17e1 j_mayer
                    a2 = ldl_phys(curaddr + 8);
989 b33c17e1 j_mayer
                    a3 = ldl_phys(curaddr + 12);
990 b33c17e1 j_mayer
                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
991 90e189ec Blue Swirl
                        qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
992 90e189ec Blue Swirl
                                 curaddr, a0, a1, a2, a3);
993 12de9a39 j_mayer
                    }
994 b33c17e1 j_mayer
                }
995 b33c17e1 j_mayer
            }
996 12de9a39 j_mayer
#endif
997 9a64fbe4 bellard
        } else {
998 d12d51d5 aliguori
            LOG_MMU("No access allowed\n");
999 76a66253 j_mayer
            ret = -3;
1000 9a64fbe4 bellard
        }
1001 9a64fbe4 bellard
    } else {
1002 d12d51d5 aliguori
        LOG_MMU("direct store...\n");
1003 9a64fbe4 bellard
        /* Direct-store segment : absolutely *BUGGY* for now */
1004 9a64fbe4 bellard
        switch (type) {
1005 9a64fbe4 bellard
        case ACCESS_INT:
1006 9a64fbe4 bellard
            /* Integer load/store : only access allowed */
1007 9a64fbe4 bellard
            break;
1008 9a64fbe4 bellard
        case ACCESS_CODE:
1009 9a64fbe4 bellard
            /* No code fetch is allowed in direct-store areas */
1010 9a64fbe4 bellard
            return -4;
1011 9a64fbe4 bellard
        case ACCESS_FLOAT:
1012 9a64fbe4 bellard
            /* Floating point load/store */
1013 9a64fbe4 bellard
            return -4;
1014 9a64fbe4 bellard
        case ACCESS_RES:
1015 9a64fbe4 bellard
            /* lwarx, ldarx or srwcx. */
1016 9a64fbe4 bellard
            return -4;
1017 9a64fbe4 bellard
        case ACCESS_CACHE:
1018 9a64fbe4 bellard
            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
1019 9a64fbe4 bellard
            /* Should make the instruction do no-op.
1020 9a64fbe4 bellard
             * As it already do no-op, it's quite easy :-)
1021 9a64fbe4 bellard
             */
1022 76a66253 j_mayer
            ctx->raddr = eaddr;
1023 9a64fbe4 bellard
            return 0;
1024 9a64fbe4 bellard
        case ACCESS_EXT:
1025 9a64fbe4 bellard
            /* eciwx or ecowx */
1026 9a64fbe4 bellard
            return -4;
1027 9a64fbe4 bellard
        default:
1028 93fcfe39 aliguori
            qemu_log("ERROR: instruction should not need "
1029 9a64fbe4 bellard
                        "address translation\n");
1030 9a64fbe4 bellard
            return -4;
1031 9a64fbe4 bellard
        }
1032 76a66253 j_mayer
        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
1033 76a66253 j_mayer
            ctx->raddr = eaddr;
1034 9a64fbe4 bellard
            ret = 2;
1035 9a64fbe4 bellard
        } else {
1036 9a64fbe4 bellard
            ret = -2;
1037 9a64fbe4 bellard
        }
1038 79aceca5 bellard
    }
1039 9a64fbe4 bellard
1040 9a64fbe4 bellard
    return ret;
1041 79aceca5 bellard
}
1042 79aceca5 bellard
1043 c294fc58 j_mayer
/* Generic TLB check function for embedded PowerPC implementations */
1044 c227f099 Anthony Liguori
static inline int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
1045 c227f099 Anthony Liguori
                                   target_phys_addr_t *raddrp,
1046 636aa200 Blue Swirl
                                   target_ulong address, uint32_t pid, int ext,
1047 636aa200 Blue Swirl
                                   int i)
1048 c294fc58 j_mayer
{
1049 c294fc58 j_mayer
    target_ulong mask;
1050 c294fc58 j_mayer
1051 c294fc58 j_mayer
    /* Check valid flag */
1052 c294fc58 j_mayer
    if (!(tlb->prot & PAGE_VALID)) {
1053 c294fc58 j_mayer
        return -1;
1054 c294fc58 j_mayer
    }
1055 c294fc58 j_mayer
    mask = ~(tlb->size - 1);
1056 90e189ec Blue Swirl
    LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
1057 90e189ec Blue Swirl
              " " TARGET_FMT_lx " %u\n", __func__, i, address, pid, tlb->EPN,
1058 90e189ec Blue Swirl
              mask, (uint32_t)tlb->PID);
1059 c294fc58 j_mayer
    /* Check PID */
1060 36081602 j_mayer
    if (tlb->PID != 0 && tlb->PID != pid)
1061 c294fc58 j_mayer
        return -1;
1062 c294fc58 j_mayer
    /* Check effective address */
1063 c294fc58 j_mayer
    if ((address & mask) != tlb->EPN)
1064 c294fc58 j_mayer
        return -1;
1065 c294fc58 j_mayer
    *raddrp = (tlb->RPN & mask) | (address & ~mask);
1066 9706285b j_mayer
#if (TARGET_PHYS_ADDR_BITS >= 36)
1067 36081602 j_mayer
    if (ext) {
1068 36081602 j_mayer
        /* Extend the physical address to 36 bits */
1069 c227f099 Anthony Liguori
        *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1070 36081602 j_mayer
    }
1071 9706285b j_mayer
#endif
1072 c294fc58 j_mayer
1073 c294fc58 j_mayer
    return 0;
1074 c294fc58 j_mayer
}
1075 c294fc58 j_mayer
1076 c294fc58 j_mayer
/* Generic TLB search function for PowerPC embedded implementations */
1077 36081602 j_mayer
int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1078 c294fc58 j_mayer
{
1079 c227f099 Anthony Liguori
    ppcemb_tlb_t *tlb;
1080 c227f099 Anthony Liguori
    target_phys_addr_t raddr;
1081 c294fc58 j_mayer
    int i, ret;
1082 c294fc58 j_mayer
1083 c294fc58 j_mayer
    /* Default return value is no match */
1084 c294fc58 j_mayer
    ret = -1;
1085 a750fc0b j_mayer
    for (i = 0; i < env->nb_tlb; i++) {
1086 c294fc58 j_mayer
        tlb = &env->tlb[i].tlbe;
1087 36081602 j_mayer
        if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1088 c294fc58 j_mayer
            ret = i;
1089 c294fc58 j_mayer
            break;
1090 c294fc58 j_mayer
        }
1091 c294fc58 j_mayer
    }
1092 c294fc58 j_mayer
1093 c294fc58 j_mayer
    return ret;
1094 c294fc58 j_mayer
}
1095 c294fc58 j_mayer
1096 daf4f96e j_mayer
/* Helpers specific to PowerPC 40x implementations */
1097 636aa200 Blue Swirl
static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
1098 a750fc0b j_mayer
{
1099 c227f099 Anthony Liguori
    ppcemb_tlb_t *tlb;
1100 a750fc0b j_mayer
    int i;
1101 a750fc0b j_mayer
1102 a750fc0b j_mayer
    for (i = 0; i < env->nb_tlb; i++) {
1103 a750fc0b j_mayer
        tlb = &env->tlb[i].tlbe;
1104 daf4f96e j_mayer
        tlb->prot &= ~PAGE_VALID;
1105 a750fc0b j_mayer
    }
1106 daf4f96e j_mayer
    tlb_flush(env, 1);
1107 a750fc0b j_mayer
}
1108 a750fc0b j_mayer
1109 636aa200 Blue Swirl
static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
1110 636aa200 Blue Swirl
                                              target_ulong eaddr, uint32_t pid)
1111 0a032cbe j_mayer
{
1112 daf4f96e j_mayer
#if !defined(FLUSH_ALL_TLBS)
1113 c227f099 Anthony Liguori
    ppcemb_tlb_t *tlb;
1114 c227f099 Anthony Liguori
    target_phys_addr_t raddr;
1115 daf4f96e j_mayer
    target_ulong page, end;
1116 0a032cbe j_mayer
    int i;
1117 0a032cbe j_mayer
1118 0a032cbe j_mayer
    for (i = 0; i < env->nb_tlb; i++) {
1119 0a032cbe j_mayer
        tlb = &env->tlb[i].tlbe;
1120 daf4f96e j_mayer
        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1121 0a032cbe j_mayer
            end = tlb->EPN + tlb->size;
1122 0a032cbe j_mayer
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1123 0a032cbe j_mayer
                tlb_flush_page(env, page);
1124 0a032cbe j_mayer
            tlb->prot &= ~PAGE_VALID;
1125 daf4f96e j_mayer
            break;
1126 0a032cbe j_mayer
        }
1127 0a032cbe j_mayer
    }
1128 daf4f96e j_mayer
#else
1129 daf4f96e j_mayer
    ppc4xx_tlb_invalidate_all(env);
1130 daf4f96e j_mayer
#endif
1131 0a032cbe j_mayer
}
1132 0a032cbe j_mayer
1133 c227f099 Anthony Liguori
static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1134 e96efcfc j_mayer
                                 target_ulong address, int rw, int access_type)
1135 a8dea12f j_mayer
{
1136 c227f099 Anthony Liguori
    ppcemb_tlb_t *tlb;
1137 c227f099 Anthony Liguori
    target_phys_addr_t raddr;
1138 0411a972 j_mayer
    int i, ret, zsel, zpr, pr;
1139 3b46e624 ths
1140 c55e9aef j_mayer
    ret = -1;
1141 c227f099 Anthony Liguori
    raddr = (target_phys_addr_t)-1ULL;
1142 0411a972 j_mayer
    pr = msr_pr;
1143 a8dea12f j_mayer
    for (i = 0; i < env->nb_tlb; i++) {
1144 a8dea12f j_mayer
        tlb = &env->tlb[i].tlbe;
1145 36081602 j_mayer
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1146 36081602 j_mayer
                             env->spr[SPR_40x_PID], 0, i) < 0)
1147 a8dea12f j_mayer
            continue;
1148 a8dea12f j_mayer
        zsel = (tlb->attr >> 4) & 0xF;
1149 ec5c3e48 Edgar E. Iglesias
        zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
1150 d12d51d5 aliguori
        LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1151 a8dea12f j_mayer
                    __func__, i, zsel, zpr, rw, tlb->attr);
1152 b227a8e9 j_mayer
        /* Check execute enable bit */
1153 b227a8e9 j_mayer
        switch (zpr) {
1154 b227a8e9 j_mayer
        case 0x2:
1155 0411a972 j_mayer
            if (pr != 0)
1156 b227a8e9 j_mayer
                goto check_perms;
1157 b227a8e9 j_mayer
            /* No break here */
1158 b227a8e9 j_mayer
        case 0x3:
1159 b227a8e9 j_mayer
            /* All accesses granted */
1160 b227a8e9 j_mayer
            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1161 b227a8e9 j_mayer
            ret = 0;
1162 b227a8e9 j_mayer
            break;
1163 b227a8e9 j_mayer
        case 0x0:
1164 0411a972 j_mayer
            if (pr != 0) {
1165 dcbc9a70 Edgar E. Iglesias
                /* Raise Zone protection fault.  */
1166 dcbc9a70 Edgar E. Iglesias
                env->spr[SPR_40x_ESR] = 1 << 22;
1167 b227a8e9 j_mayer
                ctx->prot = 0;
1168 b227a8e9 j_mayer
                ret = -2;
1169 a8dea12f j_mayer
                break;
1170 a8dea12f j_mayer
            }
1171 b227a8e9 j_mayer
            /* No break here */
1172 b227a8e9 j_mayer
        case 0x1:
1173 b227a8e9 j_mayer
        check_perms:
1174 b227a8e9 j_mayer
            /* Check from TLB entry */
1175 b227a8e9 j_mayer
            ctx->prot = tlb->prot;
1176 b227a8e9 j_mayer
            ret = check_prot(ctx->prot, rw, access_type);
1177 dcbc9a70 Edgar E. Iglesias
            if (ret == -2)
1178 dcbc9a70 Edgar E. Iglesias
                env->spr[SPR_40x_ESR] = 0;
1179 b227a8e9 j_mayer
            break;
1180 a8dea12f j_mayer
        }
1181 a8dea12f j_mayer
        if (ret >= 0) {
1182 a8dea12f j_mayer
            ctx->raddr = raddr;
1183 90e189ec Blue Swirl
            LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1184 90e189ec Blue Swirl
                      " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1185 90e189ec Blue Swirl
                      ret);
1186 c55e9aef j_mayer
            return 0;
1187 a8dea12f j_mayer
        }
1188 a8dea12f j_mayer
    }
1189 90e189ec Blue Swirl
    LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1190 90e189ec Blue Swirl
              " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1191 3b46e624 ths
1192 a8dea12f j_mayer
    return ret;
1193 a8dea12f j_mayer
}
1194 a8dea12f j_mayer
1195 c294fc58 j_mayer
void store_40x_sler (CPUPPCState *env, uint32_t val)
1196 c294fc58 j_mayer
{
1197 c294fc58 j_mayer
    /* XXX: TO BE FIXED */
1198 c294fc58 j_mayer
    if (val != 0x00000000) {
1199 c294fc58 j_mayer
        cpu_abort(env, "Little-endian regions are not supported by now\n");
1200 c294fc58 j_mayer
    }
1201 c294fc58 j_mayer
    env->spr[SPR_405_SLER] = val;
1202 c294fc58 j_mayer
}
1203 c294fc58 j_mayer
1204 c227f099 Anthony Liguori
static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1205 93220573 aurel32
                                          target_ulong address, int rw,
1206 93220573 aurel32
                                          int access_type)
1207 5eb7995e j_mayer
{
1208 c227f099 Anthony Liguori
    ppcemb_tlb_t *tlb;
1209 c227f099 Anthony Liguori
    target_phys_addr_t raddr;
1210 5eb7995e j_mayer
    int i, prot, ret;
1211 5eb7995e j_mayer
1212 5eb7995e j_mayer
    ret = -1;
1213 c227f099 Anthony Liguori
    raddr = (target_phys_addr_t)-1ULL;
1214 5eb7995e j_mayer
    for (i = 0; i < env->nb_tlb; i++) {
1215 5eb7995e j_mayer
        tlb = &env->tlb[i].tlbe;
1216 5eb7995e j_mayer
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1217 5eb7995e j_mayer
                             env->spr[SPR_BOOKE_PID], 1, i) < 0)
1218 5eb7995e j_mayer
            continue;
1219 0411a972 j_mayer
        if (msr_pr != 0)
1220 5eb7995e j_mayer
            prot = tlb->prot & 0xF;
1221 5eb7995e j_mayer
        else
1222 5eb7995e j_mayer
            prot = (tlb->prot >> 4) & 0xF;
1223 5eb7995e j_mayer
        /* Check the address space */
1224 5eb7995e j_mayer
        if (access_type == ACCESS_CODE) {
1225 d26bfc9a j_mayer
            if (msr_ir != (tlb->attr & 1))
1226 5eb7995e j_mayer
                continue;
1227 5eb7995e j_mayer
            ctx->prot = prot;
1228 5eb7995e j_mayer
            if (prot & PAGE_EXEC) {
1229 5eb7995e j_mayer
                ret = 0;
1230 5eb7995e j_mayer
                break;
1231 5eb7995e j_mayer
            }
1232 5eb7995e j_mayer
            ret = -3;
1233 5eb7995e j_mayer
        } else {
1234 d26bfc9a j_mayer
            if (msr_dr != (tlb->attr & 1))
1235 5eb7995e j_mayer
                continue;
1236 5eb7995e j_mayer
            ctx->prot = prot;
1237 5eb7995e j_mayer
            if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
1238 5eb7995e j_mayer
                ret = 0;
1239 5eb7995e j_mayer
                break;
1240 5eb7995e j_mayer
            }
1241 5eb7995e j_mayer
            ret = -2;
1242 5eb7995e j_mayer
        }
1243 5eb7995e j_mayer
    }
1244 5eb7995e j_mayer
    if (ret >= 0)
1245 5eb7995e j_mayer
        ctx->raddr = raddr;
1246 5eb7995e j_mayer
1247 5eb7995e j_mayer
    return ret;
1248 5eb7995e j_mayer
}
1249 5eb7995e j_mayer
1250 c227f099 Anthony Liguori
static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1251 636aa200 Blue Swirl
                                 target_ulong eaddr, int rw)
1252 76a66253 j_mayer
{
1253 76a66253 j_mayer
    int in_plb, ret;
1254 3b46e624 ths
1255 76a66253 j_mayer
    ctx->raddr = eaddr;
1256 b227a8e9 j_mayer
    ctx->prot = PAGE_READ | PAGE_EXEC;
1257 76a66253 j_mayer
    ret = 0;
1258 a750fc0b j_mayer
    switch (env->mmu_model) {
1259 a750fc0b j_mayer
    case POWERPC_MMU_32B:
1260 faadf50e j_mayer
    case POWERPC_MMU_601:
1261 a750fc0b j_mayer
    case POWERPC_MMU_SOFT_6xx:
1262 7dbe11ac j_mayer
    case POWERPC_MMU_SOFT_74xx:
1263 a750fc0b j_mayer
    case POWERPC_MMU_SOFT_4xx:
1264 b4095fed j_mayer
    case POWERPC_MMU_REAL:
1265 7dbe11ac j_mayer
    case POWERPC_MMU_BOOKE:
1266 caa4039c j_mayer
        ctx->prot |= PAGE_WRITE;
1267 caa4039c j_mayer
        break;
1268 caa4039c j_mayer
#if defined(TARGET_PPC64)
1269 add78955 j_mayer
    case POWERPC_MMU_620:
1270 a750fc0b j_mayer
    case POWERPC_MMU_64B:
1271 caa4039c j_mayer
        /* Real address are 60 bits long */
1272 a750fc0b j_mayer
        ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1273 caa4039c j_mayer
        ctx->prot |= PAGE_WRITE;
1274 caa4039c j_mayer
        break;
1275 9706285b j_mayer
#endif
1276 a750fc0b j_mayer
    case POWERPC_MMU_SOFT_4xx_Z:
1277 caa4039c j_mayer
        if (unlikely(msr_pe != 0)) {
1278 caa4039c j_mayer
            /* 403 family add some particular protections,
1279 caa4039c j_mayer
             * using PBL/PBU registers for accesses with no translation.
1280 caa4039c j_mayer
             */
1281 caa4039c j_mayer
            in_plb =
1282 caa4039c j_mayer
                /* Check PLB validity */
1283 caa4039c j_mayer
                (env->pb[0] < env->pb[1] &&
1284 caa4039c j_mayer
                 /* and address in plb area */
1285 caa4039c j_mayer
                 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1286 caa4039c j_mayer
                (env->pb[2] < env->pb[3] &&
1287 caa4039c j_mayer
                 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1288 caa4039c j_mayer
            if (in_plb ^ msr_px) {
1289 caa4039c j_mayer
                /* Access in protected area */
1290 caa4039c j_mayer
                if (rw == 1) {
1291 caa4039c j_mayer
                    /* Access is not allowed */
1292 caa4039c j_mayer
                    ret = -2;
1293 caa4039c j_mayer
                }
1294 caa4039c j_mayer
            } else {
1295 caa4039c j_mayer
                /* Read-write access is allowed */
1296 caa4039c j_mayer
                ctx->prot |= PAGE_WRITE;
1297 76a66253 j_mayer
            }
1298 76a66253 j_mayer
        }
1299 e1833e1f j_mayer
        break;
1300 b4095fed j_mayer
    case POWERPC_MMU_MPC8xx:
1301 b4095fed j_mayer
        /* XXX: TODO */
1302 b4095fed j_mayer
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1303 b4095fed j_mayer
        break;
1304 a750fc0b j_mayer
    case POWERPC_MMU_BOOKE_FSL:
1305 caa4039c j_mayer
        /* XXX: TODO */
1306 caa4039c j_mayer
        cpu_abort(env, "BookE FSL MMU model not implemented\n");
1307 caa4039c j_mayer
        break;
1308 caa4039c j_mayer
    default:
1309 caa4039c j_mayer
        cpu_abort(env, "Unknown or invalid MMU model\n");
1310 caa4039c j_mayer
        return -1;
1311 76a66253 j_mayer
    }
1312 76a66253 j_mayer
1313 76a66253 j_mayer
    return ret;
1314 76a66253 j_mayer
}
1315 76a66253 j_mayer
1316 c227f099 Anthony Liguori
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1317 faadf50e j_mayer
                          int rw, int access_type)
1318 9a64fbe4 bellard
{
1319 9a64fbe4 bellard
    int ret;
1320 0411a972 j_mayer
1321 514fb8c1 bellard
#if 0
1322 93fcfe39 aliguori
    qemu_log("%s\n", __func__);
1323 d9bce9d9 j_mayer
#endif
1324 4b3686fa bellard
    if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1325 4b3686fa bellard
        (access_type != ACCESS_CODE && msr_dr == 0)) {
1326 a586e548 Edgar E. Iglesias
        if (env->mmu_model == POWERPC_MMU_BOOKE) {
1327 a586e548 Edgar E. Iglesias
            /* The BookE MMU always performs address translation. The
1328 a586e548 Edgar E. Iglesias
               IS and DS bits only affect the address space.  */
1329 a586e548 Edgar E. Iglesias
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1330 a586e548 Edgar E. Iglesias
                                                rw, access_type);
1331 a586e548 Edgar E. Iglesias
        } else {
1332 a586e548 Edgar E. Iglesias
            /* No address translation.  */
1333 a586e548 Edgar E. Iglesias
            ret = check_physical(env, ctx, eaddr, rw);
1334 a586e548 Edgar E. Iglesias
        }
1335 9a64fbe4 bellard
    } else {
1336 c55e9aef j_mayer
        ret = -1;
1337 a750fc0b j_mayer
        switch (env->mmu_model) {
1338 a750fc0b j_mayer
        case POWERPC_MMU_32B:
1339 faadf50e j_mayer
        case POWERPC_MMU_601:
1340 a750fc0b j_mayer
        case POWERPC_MMU_SOFT_6xx:
1341 7dbe11ac j_mayer
        case POWERPC_MMU_SOFT_74xx:
1342 94855937 blueswir1
            /* Try to find a BAT */
1343 94855937 blueswir1
            if (env->nb_BATs != 0)
1344 94855937 blueswir1
                ret = get_bat(env, ctx, eaddr, rw, access_type);
1345 c55e9aef j_mayer
#if defined(TARGET_PPC64)
1346 add78955 j_mayer
        case POWERPC_MMU_620:
1347 a750fc0b j_mayer
        case POWERPC_MMU_64B:
1348 c55e9aef j_mayer
#endif
1349 a8dea12f j_mayer
            if (ret < 0) {
1350 c55e9aef j_mayer
                /* We didn't match any BAT entry or don't have BATs */
1351 a8dea12f j_mayer
                ret = get_segment(env, ctx, eaddr, rw, access_type);
1352 a8dea12f j_mayer
            }
1353 a8dea12f j_mayer
            break;
1354 a750fc0b j_mayer
        case POWERPC_MMU_SOFT_4xx:
1355 a750fc0b j_mayer
        case POWERPC_MMU_SOFT_4xx_Z:
1356 36081602 j_mayer
            ret = mmu40x_get_physical_address(env, ctx, eaddr,
1357 a8dea12f j_mayer
                                              rw, access_type);
1358 a8dea12f j_mayer
            break;
1359 a750fc0b j_mayer
        case POWERPC_MMU_BOOKE:
1360 5eb7995e j_mayer
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1361 5eb7995e j_mayer
                                                rw, access_type);
1362 5eb7995e j_mayer
            break;
1363 b4095fed j_mayer
        case POWERPC_MMU_MPC8xx:
1364 b4095fed j_mayer
            /* XXX: TODO */
1365 b4095fed j_mayer
            cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1366 b4095fed j_mayer
            break;
1367 a750fc0b j_mayer
        case POWERPC_MMU_BOOKE_FSL:
1368 c55e9aef j_mayer
            /* XXX: TODO */
1369 c55e9aef j_mayer
            cpu_abort(env, "BookE FSL MMU model not implemented\n");
1370 c55e9aef j_mayer
            return -1;
1371 b4095fed j_mayer
        case POWERPC_MMU_REAL:
1372 b4095fed j_mayer
            cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1373 2662a059 j_mayer
            return -1;
1374 c55e9aef j_mayer
        default:
1375 c55e9aef j_mayer
            cpu_abort(env, "Unknown or invalid MMU model\n");
1376 a8dea12f j_mayer
            return -1;
1377 9a64fbe4 bellard
        }
1378 9a64fbe4 bellard
    }
1379 514fb8c1 bellard
#if 0
1380 90e189ec Blue Swirl
    qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1381 90e189ec Blue Swirl
             __func__, eaddr, ret, ctx->raddr);
1382 76a66253 j_mayer
#endif
1383 d9bce9d9 j_mayer
1384 9a64fbe4 bellard
    return ret;
1385 9a64fbe4 bellard
}
1386 9a64fbe4 bellard
1387 c227f099 Anthony Liguori
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1388 a6b025d3 bellard
{
1389 c227f099 Anthony Liguori
    mmu_ctx_t ctx;
1390 a6b025d3 bellard
1391 faadf50e j_mayer
    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1392 a6b025d3 bellard
        return -1;
1393 76a66253 j_mayer
1394 76a66253 j_mayer
    return ctx.raddr & TARGET_PAGE_MASK;
1395 a6b025d3 bellard
}
1396 9a64fbe4 bellard
1397 9a64fbe4 bellard
/* Perform address translation */
1398 e96efcfc j_mayer
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1399 6ebbf390 j_mayer
                              int mmu_idx, int is_softmmu)
1400 9a64fbe4 bellard
{
1401 c227f099 Anthony Liguori
    mmu_ctx_t ctx;
1402 a541f297 bellard
    int access_type;
1403 9a64fbe4 bellard
    int ret = 0;
1404 d9bce9d9 j_mayer
1405 b769d8fe bellard
    if (rw == 2) {
1406 b769d8fe bellard
        /* code access */
1407 b769d8fe bellard
        rw = 0;
1408 b769d8fe bellard
        access_type = ACCESS_CODE;
1409 b769d8fe bellard
    } else {
1410 b769d8fe bellard
        /* data access */
1411 b4cec7b4 aurel32
        access_type = env->access_type;
1412 b769d8fe bellard
    }
1413 faadf50e j_mayer
    ret = get_physical_address(env, &ctx, address, rw, access_type);
1414 9a64fbe4 bellard
    if (ret == 0) {
1415 d4c430a8 Paul Brook
        tlb_set_page(env, address & TARGET_PAGE_MASK,
1416 d4c430a8 Paul Brook
                     ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1417 d4c430a8 Paul Brook
                     mmu_idx, TARGET_PAGE_SIZE);
1418 d4c430a8 Paul Brook
        ret = 0;
1419 9a64fbe4 bellard
    } else if (ret < 0) {
1420 d12d51d5 aliguori
        LOG_MMU_STATE(env);
1421 9a64fbe4 bellard
        if (access_type == ACCESS_CODE) {
1422 9a64fbe4 bellard
            switch (ret) {
1423 9a64fbe4 bellard
            case -1:
1424 76a66253 j_mayer
                /* No matches in page tables or TLB */
1425 a750fc0b j_mayer
                switch (env->mmu_model) {
1426 a750fc0b j_mayer
                case POWERPC_MMU_SOFT_6xx:
1427 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_IFTLB;
1428 8f793433 j_mayer
                    env->error_code = 1 << 18;
1429 76a66253 j_mayer
                    env->spr[SPR_IMISS] = address;
1430 76a66253 j_mayer
                    env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1431 76a66253 j_mayer
                    goto tlb_miss;
1432 7dbe11ac j_mayer
                case POWERPC_MMU_SOFT_74xx:
1433 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_IFTLB;
1434 7dbe11ac j_mayer
                    goto tlb_miss_74xx;
1435 a750fc0b j_mayer
                case POWERPC_MMU_SOFT_4xx:
1436 a750fc0b j_mayer
                case POWERPC_MMU_SOFT_4xx_Z:
1437 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_ITLB;
1438 8f793433 j_mayer
                    env->error_code = 0;
1439 a8dea12f j_mayer
                    env->spr[SPR_40x_DEAR] = address;
1440 a8dea12f j_mayer
                    env->spr[SPR_40x_ESR] = 0x00000000;
1441 c55e9aef j_mayer
                    break;
1442 a750fc0b j_mayer
                case POWERPC_MMU_32B:
1443 faadf50e j_mayer
                case POWERPC_MMU_601:
1444 c55e9aef j_mayer
#if defined(TARGET_PPC64)
1445 add78955 j_mayer
                case POWERPC_MMU_620:
1446 a750fc0b j_mayer
                case POWERPC_MMU_64B:
1447 c55e9aef j_mayer
#endif
1448 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_ISI;
1449 8f793433 j_mayer
                    env->error_code = 0x40000000;
1450 8f793433 j_mayer
                    break;
1451 a750fc0b j_mayer
                case POWERPC_MMU_BOOKE:
1452 a586e548 Edgar E. Iglesias
                    env->exception_index = POWERPC_EXCP_ITLB;
1453 a586e548 Edgar E. Iglesias
                    env->error_code = 0;
1454 a586e548 Edgar E. Iglesias
                    env->spr[SPR_BOOKE_DEAR] = address;
1455 c55e9aef j_mayer
                    return -1;
1456 a750fc0b j_mayer
                case POWERPC_MMU_BOOKE_FSL:
1457 c55e9aef j_mayer
                    /* XXX: TODO */
1458 b4095fed j_mayer
                    cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1459 c55e9aef j_mayer
                    return -1;
1460 b4095fed j_mayer
                case POWERPC_MMU_MPC8xx:
1461 b4095fed j_mayer
                    /* XXX: TODO */
1462 b4095fed j_mayer
                    cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1463 b4095fed j_mayer
                    break;
1464 b4095fed j_mayer
                case POWERPC_MMU_REAL:
1465 b4095fed j_mayer
                    cpu_abort(env, "PowerPC in real mode should never raise "
1466 b4095fed j_mayer
                              "any MMU exceptions\n");
1467 2662a059 j_mayer
                    return -1;
1468 c55e9aef j_mayer
                default:
1469 c55e9aef j_mayer
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1470 c55e9aef j_mayer
                    return -1;
1471 76a66253 j_mayer
                }
1472 9a64fbe4 bellard
                break;
1473 9a64fbe4 bellard
            case -2:
1474 9a64fbe4 bellard
                /* Access rights violation */
1475 8f793433 j_mayer
                env->exception_index = POWERPC_EXCP_ISI;
1476 8f793433 j_mayer
                env->error_code = 0x08000000;
1477 9a64fbe4 bellard
                break;
1478 9a64fbe4 bellard
            case -3:
1479 76a66253 j_mayer
                /* No execute protection violation */
1480 a586e548 Edgar E. Iglesias
                if (env->mmu_model == POWERPC_MMU_BOOKE) {
1481 a586e548 Edgar E. Iglesias
                    env->spr[SPR_BOOKE_ESR] = 0x00000000;
1482 a586e548 Edgar E. Iglesias
                }
1483 8f793433 j_mayer
                env->exception_index = POWERPC_EXCP_ISI;
1484 8f793433 j_mayer
                env->error_code = 0x10000000;
1485 9a64fbe4 bellard
                break;
1486 9a64fbe4 bellard
            case -4:
1487 9a64fbe4 bellard
                /* Direct store exception */
1488 9a64fbe4 bellard
                /* No code fetch is allowed in direct-store areas */
1489 8f793433 j_mayer
                env->exception_index = POWERPC_EXCP_ISI;
1490 8f793433 j_mayer
                env->error_code = 0x10000000;
1491 2be0071f bellard
                break;
1492 e1833e1f j_mayer
#if defined(TARGET_PPC64)
1493 2be0071f bellard
            case -5:
1494 2be0071f bellard
                /* No match in segment table */
1495 add78955 j_mayer
                if (env->mmu_model == POWERPC_MMU_620) {
1496 add78955 j_mayer
                    env->exception_index = POWERPC_EXCP_ISI;
1497 add78955 j_mayer
                    /* XXX: this might be incorrect */
1498 add78955 j_mayer
                    env->error_code = 0x40000000;
1499 add78955 j_mayer
                } else {
1500 add78955 j_mayer
                    env->exception_index = POWERPC_EXCP_ISEG;
1501 add78955 j_mayer
                    env->error_code = 0;
1502 add78955 j_mayer
                }
1503 9a64fbe4 bellard
                break;
1504 e1833e1f j_mayer
#endif
1505 9a64fbe4 bellard
            }
1506 9a64fbe4 bellard
        } else {
1507 9a64fbe4 bellard
            switch (ret) {
1508 9a64fbe4 bellard
            case -1:
1509 76a66253 j_mayer
                /* No matches in page tables or TLB */
1510 a750fc0b j_mayer
                switch (env->mmu_model) {
1511 a750fc0b j_mayer
                case POWERPC_MMU_SOFT_6xx:
1512 76a66253 j_mayer
                    if (rw == 1) {
1513 8f793433 j_mayer
                        env->exception_index = POWERPC_EXCP_DSTLB;
1514 8f793433 j_mayer
                        env->error_code = 1 << 16;
1515 76a66253 j_mayer
                    } else {
1516 8f793433 j_mayer
                        env->exception_index = POWERPC_EXCP_DLTLB;
1517 8f793433 j_mayer
                        env->error_code = 0;
1518 76a66253 j_mayer
                    }
1519 76a66253 j_mayer
                    env->spr[SPR_DMISS] = address;
1520 76a66253 j_mayer
                    env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1521 76a66253 j_mayer
                tlb_miss:
1522 8f793433 j_mayer
                    env->error_code |= ctx.key << 19;
1523 76a66253 j_mayer
                    env->spr[SPR_HASH1] = ctx.pg_addr[0];
1524 76a66253 j_mayer
                    env->spr[SPR_HASH2] = ctx.pg_addr[1];
1525 8f793433 j_mayer
                    break;
1526 7dbe11ac j_mayer
                case POWERPC_MMU_SOFT_74xx:
1527 7dbe11ac j_mayer
                    if (rw == 1) {
1528 8f793433 j_mayer
                        env->exception_index = POWERPC_EXCP_DSTLB;
1529 7dbe11ac j_mayer
                    } else {
1530 8f793433 j_mayer
                        env->exception_index = POWERPC_EXCP_DLTLB;
1531 7dbe11ac j_mayer
                    }
1532 7dbe11ac j_mayer
                tlb_miss_74xx:
1533 7dbe11ac j_mayer
                    /* Implement LRU algorithm */
1534 8f793433 j_mayer
                    env->error_code = ctx.key << 19;
1535 7dbe11ac j_mayer
                    env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1536 7dbe11ac j_mayer
                        ((env->last_way + 1) & (env->nb_ways - 1));
1537 7dbe11ac j_mayer
                    env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1538 7dbe11ac j_mayer
                    break;
1539 a750fc0b j_mayer
                case POWERPC_MMU_SOFT_4xx:
1540 a750fc0b j_mayer
                case POWERPC_MMU_SOFT_4xx_Z:
1541 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_DTLB;
1542 8f793433 j_mayer
                    env->error_code = 0;
1543 a8dea12f j_mayer
                    env->spr[SPR_40x_DEAR] = address;
1544 a8dea12f j_mayer
                    if (rw)
1545 a8dea12f j_mayer
                        env->spr[SPR_40x_ESR] = 0x00800000;
1546 a8dea12f j_mayer
                    else
1547 a8dea12f j_mayer
                        env->spr[SPR_40x_ESR] = 0x00000000;
1548 c55e9aef j_mayer
                    break;
1549 a750fc0b j_mayer
                case POWERPC_MMU_32B:
1550 faadf50e j_mayer
                case POWERPC_MMU_601:
1551 c55e9aef j_mayer
#if defined(TARGET_PPC64)
1552 add78955 j_mayer
                case POWERPC_MMU_620:
1553 a750fc0b j_mayer
                case POWERPC_MMU_64B:
1554 c55e9aef j_mayer
#endif
1555 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_DSI;
1556 8f793433 j_mayer
                    env->error_code = 0;
1557 8f793433 j_mayer
                    env->spr[SPR_DAR] = address;
1558 8f793433 j_mayer
                    if (rw == 1)
1559 8f793433 j_mayer
                        env->spr[SPR_DSISR] = 0x42000000;
1560 8f793433 j_mayer
                    else
1561 8f793433 j_mayer
                        env->spr[SPR_DSISR] = 0x40000000;
1562 8f793433 j_mayer
                    break;
1563 b4095fed j_mayer
                case POWERPC_MMU_MPC8xx:
1564 b4095fed j_mayer
                    /* XXX: TODO */
1565 b4095fed j_mayer
                    cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1566 b4095fed j_mayer
                    break;
1567 a750fc0b j_mayer
                case POWERPC_MMU_BOOKE:
1568 a586e548 Edgar E. Iglesias
                    env->exception_index = POWERPC_EXCP_DTLB;
1569 a586e548 Edgar E. Iglesias
                    env->error_code = 0;
1570 a586e548 Edgar E. Iglesias
                    env->spr[SPR_BOOKE_DEAR] = address;
1571 a586e548 Edgar E. Iglesias
                    env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1572 c55e9aef j_mayer
                    return -1;
1573 a750fc0b j_mayer
                case POWERPC_MMU_BOOKE_FSL:
1574 c55e9aef j_mayer
                    /* XXX: TODO */
1575 b4095fed j_mayer
                    cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1576 c55e9aef j_mayer
                    return -1;
1577 b4095fed j_mayer
                case POWERPC_MMU_REAL:
1578 b4095fed j_mayer
                    cpu_abort(env, "PowerPC in real mode should never raise "
1579 b4095fed j_mayer
                              "any MMU exceptions\n");
1580 2662a059 j_mayer
                    return -1;
1581 c55e9aef j_mayer
                default:
1582 c55e9aef j_mayer
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1583 c55e9aef j_mayer
                    return -1;
1584 76a66253 j_mayer
                }
1585 9a64fbe4 bellard
                break;
1586 9a64fbe4 bellard
            case -2:
1587 9a64fbe4 bellard
                /* Access rights violation */
1588 8f793433 j_mayer
                env->exception_index = POWERPC_EXCP_DSI;
1589 8f793433 j_mayer
                env->error_code = 0;
1590 dcbc9a70 Edgar E. Iglesias
                if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1591 dcbc9a70 Edgar E. Iglesias
                    || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1592 dcbc9a70 Edgar E. Iglesias
                    env->spr[SPR_40x_DEAR] = address;
1593 dcbc9a70 Edgar E. Iglesias
                    if (rw) {
1594 dcbc9a70 Edgar E. Iglesias
                        env->spr[SPR_40x_ESR] |= 0x00800000;
1595 dcbc9a70 Edgar E. Iglesias
                    }
1596 a586e548 Edgar E. Iglesias
                } else if (env->mmu_model == POWERPC_MMU_BOOKE) {
1597 a586e548 Edgar E. Iglesias
                    env->spr[SPR_BOOKE_DEAR] = address;
1598 a586e548 Edgar E. Iglesias
                    env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1599 dcbc9a70 Edgar E. Iglesias
                } else {
1600 dcbc9a70 Edgar E. Iglesias
                    env->spr[SPR_DAR] = address;
1601 dcbc9a70 Edgar E. Iglesias
                    if (rw == 1) {
1602 dcbc9a70 Edgar E. Iglesias
                        env->spr[SPR_DSISR] = 0x0A000000;
1603 dcbc9a70 Edgar E. Iglesias
                    } else {
1604 dcbc9a70 Edgar E. Iglesias
                        env->spr[SPR_DSISR] = 0x08000000;
1605 dcbc9a70 Edgar E. Iglesias
                    }
1606 dcbc9a70 Edgar E. Iglesias
                }
1607 9a64fbe4 bellard
                break;
1608 9a64fbe4 bellard
            case -4:
1609 9a64fbe4 bellard
                /* Direct store exception */
1610 9a64fbe4 bellard
                switch (access_type) {
1611 9a64fbe4 bellard
                case ACCESS_FLOAT:
1612 9a64fbe4 bellard
                    /* Floating point load/store */
1613 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_ALIGN;
1614 8f793433 j_mayer
                    env->error_code = POWERPC_EXCP_ALIGN_FP;
1615 8f793433 j_mayer
                    env->spr[SPR_DAR] = address;
1616 9a64fbe4 bellard
                    break;
1617 9a64fbe4 bellard
                case ACCESS_RES:
1618 8f793433 j_mayer
                    /* lwarx, ldarx or stwcx. */
1619 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_DSI;
1620 8f793433 j_mayer
                    env->error_code = 0;
1621 8f793433 j_mayer
                    env->spr[SPR_DAR] = address;
1622 8f793433 j_mayer
                    if (rw == 1)
1623 8f793433 j_mayer
                        env->spr[SPR_DSISR] = 0x06000000;
1624 8f793433 j_mayer
                    else
1625 8f793433 j_mayer
                        env->spr[SPR_DSISR] = 0x04000000;
1626 9a64fbe4 bellard
                    break;
1627 9a64fbe4 bellard
                case ACCESS_EXT:
1628 9a64fbe4 bellard
                    /* eciwx or ecowx */
1629 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_DSI;
1630 8f793433 j_mayer
                    env->error_code = 0;
1631 8f793433 j_mayer
                    env->spr[SPR_DAR] = address;
1632 8f793433 j_mayer
                    if (rw == 1)
1633 8f793433 j_mayer
                        env->spr[SPR_DSISR] = 0x06100000;
1634 8f793433 j_mayer
                    else
1635 8f793433 j_mayer
                        env->spr[SPR_DSISR] = 0x04100000;
1636 9a64fbe4 bellard
                    break;
1637 9a64fbe4 bellard
                default:
1638 76a66253 j_mayer
                    printf("DSI: invalid exception (%d)\n", ret);
1639 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_PROGRAM;
1640 8f793433 j_mayer
                    env->error_code =
1641 8f793433 j_mayer
                        POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1642 8f793433 j_mayer
                    env->spr[SPR_DAR] = address;
1643 9a64fbe4 bellard
                    break;
1644 9a64fbe4 bellard
                }
1645 fdabc366 bellard
                break;
1646 e1833e1f j_mayer
#if defined(TARGET_PPC64)
1647 2be0071f bellard
            case -5:
1648 2be0071f bellard
                /* No match in segment table */
1649 add78955 j_mayer
                if (env->mmu_model == POWERPC_MMU_620) {
1650 add78955 j_mayer
                    env->exception_index = POWERPC_EXCP_DSI;
1651 add78955 j_mayer
                    env->error_code = 0;
1652 add78955 j_mayer
                    env->spr[SPR_DAR] = address;
1653 add78955 j_mayer
                    /* XXX: this might be incorrect */
1654 add78955 j_mayer
                    if (rw == 1)
1655 add78955 j_mayer
                        env->spr[SPR_DSISR] = 0x42000000;
1656 add78955 j_mayer
                    else
1657 add78955 j_mayer
                        env->spr[SPR_DSISR] = 0x40000000;
1658 add78955 j_mayer
                } else {
1659 add78955 j_mayer
                    env->exception_index = POWERPC_EXCP_DSEG;
1660 add78955 j_mayer
                    env->error_code = 0;
1661 add78955 j_mayer
                    env->spr[SPR_DAR] = address;
1662 add78955 j_mayer
                }
1663 2be0071f bellard
                break;
1664 e1833e1f j_mayer
#endif
1665 9a64fbe4 bellard
            }
1666 9a64fbe4 bellard
        }
1667 9a64fbe4 bellard
#if 0
1668 8f793433 j_mayer
        printf("%s: set exception to %d %02x\n", __func__,
1669 8f793433 j_mayer
               env->exception, env->error_code);
1670 9a64fbe4 bellard
#endif
1671 9a64fbe4 bellard
        ret = 1;
1672 9a64fbe4 bellard
    }
1673 76a66253 j_mayer
1674 9a64fbe4 bellard
    return ret;
1675 9a64fbe4 bellard
}
1676 9a64fbe4 bellard
1677 3fc6c082 bellard
/*****************************************************************************/
1678 3fc6c082 bellard
/* BATs management */
1679 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
1680 636aa200 Blue Swirl
static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1681 636aa200 Blue Swirl
                                     target_ulong mask)
1682 3fc6c082 bellard
{
1683 3fc6c082 bellard
    target_ulong base, end, page;
1684 76a66253 j_mayer
1685 3fc6c082 bellard
    base = BATu & ~0x0001FFFF;
1686 3fc6c082 bellard
    end = base + mask + 0x00020000;
1687 90e189ec Blue Swirl
    LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1688 90e189ec Blue Swirl
             TARGET_FMT_lx ")\n", base, end, mask);
1689 3fc6c082 bellard
    for (page = base; page != end; page += TARGET_PAGE_SIZE)
1690 3fc6c082 bellard
        tlb_flush_page(env, page);
1691 d12d51d5 aliguori
    LOG_BATS("Flush done\n");
1692 3fc6c082 bellard
}
1693 3fc6c082 bellard
#endif
1694 3fc6c082 bellard
1695 636aa200 Blue Swirl
static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1696 636aa200 Blue Swirl
                                  target_ulong value)
1697 3fc6c082 bellard
{
1698 90e189ec Blue Swirl
    LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1699 90e189ec Blue Swirl
             nr, ul == 0 ? 'u' : 'l', value, env->nip);
1700 3fc6c082 bellard
}
1701 3fc6c082 bellard
1702 45d827d2 aurel32
void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1703 3fc6c082 bellard
{
1704 3fc6c082 bellard
    target_ulong mask;
1705 3fc6c082 bellard
1706 3fc6c082 bellard
    dump_store_bat(env, 'I', 0, nr, value);
1707 3fc6c082 bellard
    if (env->IBAT[0][nr] != value) {
1708 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
1709 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
1710 3fc6c082 bellard
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1711 3fc6c082 bellard
#endif
1712 3fc6c082 bellard
        /* When storing valid upper BAT, mask BEPI and BRPN
1713 3fc6c082 bellard
         * and invalidate all TLBs covered by this BAT
1714 3fc6c082 bellard
         */
1715 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
1716 3fc6c082 bellard
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1717 3fc6c082 bellard
            (value & ~0x0001FFFFUL & ~mask);
1718 3fc6c082 bellard
        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1719 3fc6c082 bellard
            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1720 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
1721 3fc6c082 bellard
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1722 76a66253 j_mayer
#else
1723 3fc6c082 bellard
        tlb_flush(env, 1);
1724 3fc6c082 bellard
#endif
1725 3fc6c082 bellard
    }
1726 3fc6c082 bellard
}
1727 3fc6c082 bellard
1728 45d827d2 aurel32
void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1729 3fc6c082 bellard
{
1730 3fc6c082 bellard
    dump_store_bat(env, 'I', 1, nr, value);
1731 3fc6c082 bellard
    env->IBAT[1][nr] = value;
1732 3fc6c082 bellard
}
1733 3fc6c082 bellard
1734 45d827d2 aurel32
void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1735 3fc6c082 bellard
{
1736 3fc6c082 bellard
    target_ulong mask;
1737 3fc6c082 bellard
1738 3fc6c082 bellard
    dump_store_bat(env, 'D', 0, nr, value);
1739 3fc6c082 bellard
    if (env->DBAT[0][nr] != value) {
1740 3fc6c082 bellard
        /* When storing valid upper BAT, mask BEPI and BRPN
1741 3fc6c082 bellard
         * and invalidate all TLBs covered by this BAT
1742 3fc6c082 bellard
         */
1743 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
1744 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
1745 3fc6c082 bellard
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1746 3fc6c082 bellard
#endif
1747 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
1748 3fc6c082 bellard
        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1749 3fc6c082 bellard
            (value & ~0x0001FFFFUL & ~mask);
1750 3fc6c082 bellard
        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1751 3fc6c082 bellard
            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1752 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
1753 3fc6c082 bellard
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1754 3fc6c082 bellard
#else
1755 3fc6c082 bellard
        tlb_flush(env, 1);
1756 3fc6c082 bellard
#endif
1757 3fc6c082 bellard
    }
1758 3fc6c082 bellard
}
1759 3fc6c082 bellard
1760 45d827d2 aurel32
void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1761 3fc6c082 bellard
{
1762 3fc6c082 bellard
    dump_store_bat(env, 'D', 1, nr, value);
1763 3fc6c082 bellard
    env->DBAT[1][nr] = value;
1764 3fc6c082 bellard
}
1765 3fc6c082 bellard
1766 45d827d2 aurel32
void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1767 056401ea j_mayer
{
1768 056401ea j_mayer
    target_ulong mask;
1769 05f92404 Blue Swirl
#if defined(FLUSH_ALL_TLBS)
1770 056401ea j_mayer
    int do_inval;
1771 05f92404 Blue Swirl
#endif
1772 056401ea j_mayer
1773 056401ea j_mayer
    dump_store_bat(env, 'I', 0, nr, value);
1774 056401ea j_mayer
    if (env->IBAT[0][nr] != value) {
1775 05f92404 Blue Swirl
#if defined(FLUSH_ALL_TLBS)
1776 056401ea j_mayer
        do_inval = 0;
1777 05f92404 Blue Swirl
#endif
1778 056401ea j_mayer
        mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1779 056401ea j_mayer
        if (env->IBAT[1][nr] & 0x40) {
1780 056401ea j_mayer
            /* Invalidate BAT only if it is valid */
1781 056401ea j_mayer
#if !defined(FLUSH_ALL_TLBS)
1782 056401ea j_mayer
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1783 056401ea j_mayer
#else
1784 056401ea j_mayer
            do_inval = 1;
1785 056401ea j_mayer
#endif
1786 056401ea j_mayer
        }
1787 056401ea j_mayer
        /* When storing valid upper BAT, mask BEPI and BRPN
1788 056401ea j_mayer
         * and invalidate all TLBs covered by this BAT
1789 056401ea j_mayer
         */
1790 056401ea j_mayer
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1791 056401ea j_mayer
            (value & ~0x0001FFFFUL & ~mask);
1792 056401ea j_mayer
        env->DBAT[0][nr] = env->IBAT[0][nr];
1793 056401ea j_mayer
        if (env->IBAT[1][nr] & 0x40) {
1794 056401ea j_mayer
#if !defined(FLUSH_ALL_TLBS)
1795 056401ea j_mayer
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1796 056401ea j_mayer
#else
1797 056401ea j_mayer
            do_inval = 1;
1798 056401ea j_mayer
#endif
1799 056401ea j_mayer
        }
1800 056401ea j_mayer
#if defined(FLUSH_ALL_TLBS)
1801 056401ea j_mayer
        if (do_inval)
1802 056401ea j_mayer
            tlb_flush(env, 1);
1803 056401ea j_mayer
#endif
1804 056401ea j_mayer
    }
1805 056401ea j_mayer
}
1806 056401ea j_mayer
1807 45d827d2 aurel32
void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1808 056401ea j_mayer
{
1809 056401ea j_mayer
    target_ulong mask;
1810 05f92404 Blue Swirl
#if defined(FLUSH_ALL_TLBS)
1811 056401ea j_mayer
    int do_inval;
1812 05f92404 Blue Swirl
#endif
1813 056401ea j_mayer
1814 056401ea j_mayer
    dump_store_bat(env, 'I', 1, nr, value);
1815 056401ea j_mayer
    if (env->IBAT[1][nr] != value) {
1816 05f92404 Blue Swirl
#if defined(FLUSH_ALL_TLBS)
1817 056401ea j_mayer
        do_inval = 0;
1818 05f92404 Blue Swirl
#endif
1819 056401ea j_mayer
        if (env->IBAT[1][nr] & 0x40) {
1820 056401ea j_mayer
#if !defined(FLUSH_ALL_TLBS)
1821 056401ea j_mayer
            mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1822 056401ea j_mayer
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1823 056401ea j_mayer
#else
1824 056401ea j_mayer
            do_inval = 1;
1825 056401ea j_mayer
#endif
1826 056401ea j_mayer
        }
1827 056401ea j_mayer
        if (value & 0x40) {
1828 056401ea j_mayer
#if !defined(FLUSH_ALL_TLBS)
1829 056401ea j_mayer
            mask = (value << 17) & 0x0FFE0000UL;
1830 056401ea j_mayer
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1831 056401ea j_mayer
#else
1832 056401ea j_mayer
            do_inval = 1;
1833 056401ea j_mayer
#endif
1834 056401ea j_mayer
        }
1835 056401ea j_mayer
        env->IBAT[1][nr] = value;
1836 056401ea j_mayer
        env->DBAT[1][nr] = value;
1837 056401ea j_mayer
#if defined(FLUSH_ALL_TLBS)
1838 056401ea j_mayer
        if (do_inval)
1839 056401ea j_mayer
            tlb_flush(env, 1);
1840 056401ea j_mayer
#endif
1841 056401ea j_mayer
    }
1842 056401ea j_mayer
}
1843 056401ea j_mayer
1844 0a032cbe j_mayer
/*****************************************************************************/
1845 0a032cbe j_mayer
/* TLB management */
1846 0a032cbe j_mayer
void ppc_tlb_invalidate_all (CPUPPCState *env)
1847 0a032cbe j_mayer
{
1848 daf4f96e j_mayer
    switch (env->mmu_model) {
1849 daf4f96e j_mayer
    case POWERPC_MMU_SOFT_6xx:
1850 7dbe11ac j_mayer
    case POWERPC_MMU_SOFT_74xx:
1851 0a032cbe j_mayer
        ppc6xx_tlb_invalidate_all(env);
1852 daf4f96e j_mayer
        break;
1853 daf4f96e j_mayer
    case POWERPC_MMU_SOFT_4xx:
1854 daf4f96e j_mayer
    case POWERPC_MMU_SOFT_4xx_Z:
1855 0a032cbe j_mayer
        ppc4xx_tlb_invalidate_all(env);
1856 daf4f96e j_mayer
        break;
1857 b4095fed j_mayer
    case POWERPC_MMU_REAL:
1858 7dbe11ac j_mayer
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1859 7dbe11ac j_mayer
        break;
1860 b4095fed j_mayer
    case POWERPC_MMU_MPC8xx:
1861 b4095fed j_mayer
        /* XXX: TODO */
1862 b4095fed j_mayer
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1863 b4095fed j_mayer
        break;
1864 7dbe11ac j_mayer
    case POWERPC_MMU_BOOKE:
1865 a586e548 Edgar E. Iglesias
        tlb_flush(env, 1);
1866 7dbe11ac j_mayer
        break;
1867 7dbe11ac j_mayer
    case POWERPC_MMU_BOOKE_FSL:
1868 7dbe11ac j_mayer
        /* XXX: TODO */
1869 da07cf59 aliguori
        if (!kvm_enabled())
1870 da07cf59 aliguori
            cpu_abort(env, "BookE MMU model is not implemented\n");
1871 7dbe11ac j_mayer
        break;
1872 7dbe11ac j_mayer
    case POWERPC_MMU_32B:
1873 faadf50e j_mayer
    case POWERPC_MMU_601:
1874 00af685f j_mayer
#if defined(TARGET_PPC64)
1875 add78955 j_mayer
    case POWERPC_MMU_620:
1876 7dbe11ac j_mayer
    case POWERPC_MMU_64B:
1877 00af685f j_mayer
#endif /* defined(TARGET_PPC64) */
1878 0a032cbe j_mayer
        tlb_flush(env, 1);
1879 daf4f96e j_mayer
        break;
1880 00af685f j_mayer
    default:
1881 00af685f j_mayer
        /* XXX: TODO */
1882 12de9a39 j_mayer
        cpu_abort(env, "Unknown MMU model\n");
1883 00af685f j_mayer
        break;
1884 0a032cbe j_mayer
    }
1885 0a032cbe j_mayer
}
1886 0a032cbe j_mayer
1887 daf4f96e j_mayer
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
1888 daf4f96e j_mayer
{
1889 daf4f96e j_mayer
#if !defined(FLUSH_ALL_TLBS)
1890 daf4f96e j_mayer
    addr &= TARGET_PAGE_MASK;
1891 daf4f96e j_mayer
    switch (env->mmu_model) {
1892 daf4f96e j_mayer
    case POWERPC_MMU_SOFT_6xx:
1893 7dbe11ac j_mayer
    case POWERPC_MMU_SOFT_74xx:
1894 daf4f96e j_mayer
        ppc6xx_tlb_invalidate_virt(env, addr, 0);
1895 daf4f96e j_mayer
        if (env->id_tlbs == 1)
1896 daf4f96e j_mayer
            ppc6xx_tlb_invalidate_virt(env, addr, 1);
1897 daf4f96e j_mayer
        break;
1898 daf4f96e j_mayer
    case POWERPC_MMU_SOFT_4xx:
1899 daf4f96e j_mayer
    case POWERPC_MMU_SOFT_4xx_Z:
1900 daf4f96e j_mayer
        ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
1901 daf4f96e j_mayer
        break;
1902 b4095fed j_mayer
    case POWERPC_MMU_REAL:
1903 7dbe11ac j_mayer
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1904 7dbe11ac j_mayer
        break;
1905 b4095fed j_mayer
    case POWERPC_MMU_MPC8xx:
1906 b4095fed j_mayer
        /* XXX: TODO */
1907 b4095fed j_mayer
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1908 b4095fed j_mayer
        break;
1909 7dbe11ac j_mayer
    case POWERPC_MMU_BOOKE:
1910 7dbe11ac j_mayer
        /* XXX: TODO */
1911 b4095fed j_mayer
        cpu_abort(env, "BookE MMU model is not implemented\n");
1912 7dbe11ac j_mayer
        break;
1913 7dbe11ac j_mayer
    case POWERPC_MMU_BOOKE_FSL:
1914 7dbe11ac j_mayer
        /* XXX: TODO */
1915 b4095fed j_mayer
        cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1916 7dbe11ac j_mayer
        break;
1917 7dbe11ac j_mayer
    case POWERPC_MMU_32B:
1918 faadf50e j_mayer
    case POWERPC_MMU_601:
1919 daf4f96e j_mayer
        /* tlbie invalidate TLBs for all segments */
1920 6f2d8978 j_mayer
        addr &= ~((target_ulong)-1ULL << 28);
1921 daf4f96e j_mayer
        /* XXX: this case should be optimized,
1922 daf4f96e j_mayer
         * giving a mask to tlb_flush_page
1923 daf4f96e j_mayer
         */
1924 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x0 << 28));
1925 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x1 << 28));
1926 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x2 << 28));
1927 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x3 << 28));
1928 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x4 << 28));
1929 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x5 << 28));
1930 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x6 << 28));
1931 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x7 << 28));
1932 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x8 << 28));
1933 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x9 << 28));
1934 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0xA << 28));
1935 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0xB << 28));
1936 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0xC << 28));
1937 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0xD << 28));
1938 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0xE << 28));
1939 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0xF << 28));
1940 7dbe11ac j_mayer
        break;
1941 00af685f j_mayer
#if defined(TARGET_PPC64)
1942 add78955 j_mayer
    case POWERPC_MMU_620:
1943 7dbe11ac j_mayer
    case POWERPC_MMU_64B:
1944 7dbe11ac j_mayer
        /* tlbie invalidate TLBs for all segments */
1945 7dbe11ac j_mayer
        /* XXX: given the fact that there are too many segments to invalidate,
1946 00af685f j_mayer
         *      and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
1947 7dbe11ac j_mayer
         *      we just invalidate all TLBs
1948 7dbe11ac j_mayer
         */
1949 7dbe11ac j_mayer
        tlb_flush(env, 1);
1950 7dbe11ac j_mayer
        break;
1951 00af685f j_mayer
#endif /* defined(TARGET_PPC64) */
1952 00af685f j_mayer
    default:
1953 00af685f j_mayer
        /* XXX: TODO */
1954 12de9a39 j_mayer
        cpu_abort(env, "Unknown MMU model\n");
1955 00af685f j_mayer
        break;
1956 daf4f96e j_mayer
    }
1957 daf4f96e j_mayer
#else
1958 daf4f96e j_mayer
    ppc_tlb_invalidate_all(env);
1959 daf4f96e j_mayer
#endif
1960 daf4f96e j_mayer
}
1961 daf4f96e j_mayer
1962 3fc6c082 bellard
/*****************************************************************************/
1963 3fc6c082 bellard
/* Special registers manipulation */
1964 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1965 d9bce9d9 j_mayer
void ppc_store_asr (CPUPPCState *env, target_ulong value)
1966 d9bce9d9 j_mayer
{
1967 d9bce9d9 j_mayer
    if (env->asr != value) {
1968 d9bce9d9 j_mayer
        env->asr = value;
1969 d9bce9d9 j_mayer
        tlb_flush(env, 1);
1970 d9bce9d9 j_mayer
    }
1971 d9bce9d9 j_mayer
}
1972 d9bce9d9 j_mayer
#endif
1973 d9bce9d9 j_mayer
1974 45d827d2 aurel32
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
1975 3fc6c082 bellard
{
1976 90e189ec Blue Swirl
    LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
1977 3fc6c082 bellard
    if (env->sdr1 != value) {
1978 12de9a39 j_mayer
        /* XXX: for PowerPC 64, should check that the HTABSIZE value
1979 12de9a39 j_mayer
         *      is <= 28
1980 12de9a39 j_mayer
         */
1981 3fc6c082 bellard
        env->sdr1 = value;
1982 76a66253 j_mayer
        tlb_flush(env, 1);
1983 3fc6c082 bellard
    }
1984 3fc6c082 bellard
}
1985 3fc6c082 bellard
1986 f6b868fc blueswir1
#if defined(TARGET_PPC64)
1987 f6b868fc blueswir1
target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
1988 f6b868fc blueswir1
{
1989 f6b868fc blueswir1
    // XXX
1990 f6b868fc blueswir1
    return 0;
1991 f6b868fc blueswir1
}
1992 f6b868fc blueswir1
#endif
1993 f6b868fc blueswir1
1994 45d827d2 aurel32
void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1995 3fc6c082 bellard
{
1996 90e189ec Blue Swirl
    LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
1997 90e189ec Blue Swirl
            srnum, value, env->sr[srnum]);
1998 f6b868fc blueswir1
#if defined(TARGET_PPC64)
1999 f6b868fc blueswir1
    if (env->mmu_model & POWERPC_MMU_64) {
2000 f6b868fc blueswir1
        uint64_t rb = 0, rs = 0;
2001 f6b868fc blueswir1
2002 f6b868fc blueswir1
        /* ESID = srnum */
2003 f6b868fc blueswir1
        rb |= ((uint32_t)srnum & 0xf) << 28;
2004 f6b868fc blueswir1
        /* Set the valid bit */
2005 f6b868fc blueswir1
        rb |= 1 << 27;
2006 f6b868fc blueswir1
        /* Index = ESID */
2007 f6b868fc blueswir1
        rb |= (uint32_t)srnum;
2008 f6b868fc blueswir1
2009 f6b868fc blueswir1
        /* VSID = VSID */
2010 f6b868fc blueswir1
        rs |= (value & 0xfffffff) << 12;
2011 f6b868fc blueswir1
        /* flags = flags */
2012 f6b868fc blueswir1
        rs |= ((value >> 27) & 0xf) << 9;
2013 f6b868fc blueswir1
2014 f6b868fc blueswir1
        ppc_store_slb(env, rb, rs);
2015 f6b868fc blueswir1
    } else
2016 f6b868fc blueswir1
#endif
2017 3fc6c082 bellard
    if (env->sr[srnum] != value) {
2018 3fc6c082 bellard
        env->sr[srnum] = value;
2019 bf1752ef aurel32
/* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2020 bf1752ef aurel32
   flusing the whole TLB. */
2021 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS) && 0
2022 3fc6c082 bellard
        {
2023 3fc6c082 bellard
            target_ulong page, end;
2024 3fc6c082 bellard
            /* Invalidate 256 MB of virtual memory */
2025 3fc6c082 bellard
            page = (16 << 20) * srnum;
2026 3fc6c082 bellard
            end = page + (16 << 20);
2027 3fc6c082 bellard
            for (; page != end; page += TARGET_PAGE_SIZE)
2028 3fc6c082 bellard
                tlb_flush_page(env, page);
2029 3fc6c082 bellard
        }
2030 3fc6c082 bellard
#else
2031 76a66253 j_mayer
        tlb_flush(env, 1);
2032 3fc6c082 bellard
#endif
2033 3fc6c082 bellard
    }
2034 3fc6c082 bellard
}
2035 76a66253 j_mayer
#endif /* !defined (CONFIG_USER_ONLY) */
2036 3fc6c082 bellard
2037 76a66253 j_mayer
/* GDBstub can read and write MSR... */
2038 0411a972 j_mayer
void ppc_store_msr (CPUPPCState *env, target_ulong value)
2039 3fc6c082 bellard
{
2040 a4f30719 j_mayer
    hreg_store_msr(env, value, 0);
2041 3fc6c082 bellard
}
2042 3fc6c082 bellard
2043 3fc6c082 bellard
/*****************************************************************************/
2044 3fc6c082 bellard
/* Exception processing */
2045 18fba28c bellard
#if defined (CONFIG_USER_ONLY)
2046 9a64fbe4 bellard
void do_interrupt (CPUState *env)
2047 79aceca5 bellard
{
2048 e1833e1f j_mayer
    env->exception_index = POWERPC_EXCP_NONE;
2049 e1833e1f j_mayer
    env->error_code = 0;
2050 18fba28c bellard
}
2051 47103572 j_mayer
2052 e9df014c j_mayer
void ppc_hw_interrupt (CPUState *env)
2053 47103572 j_mayer
{
2054 e1833e1f j_mayer
    env->exception_index = POWERPC_EXCP_NONE;
2055 e1833e1f j_mayer
    env->error_code = 0;
2056 47103572 j_mayer
}
2057 76a66253 j_mayer
#else /* defined (CONFIG_USER_ONLY) */
2058 636aa200 Blue Swirl
static inline void dump_syscall(CPUState *env)
2059 d094807b bellard
{
2060 b11ebf64 Blue Swirl
    qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2061 b11ebf64 Blue Swirl
                  " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2062 b11ebf64 Blue Swirl
                  " nip=" TARGET_FMT_lx "\n",
2063 90e189ec Blue Swirl
                  ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2064 90e189ec Blue Swirl
                  ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2065 90e189ec Blue Swirl
                  ppc_dump_gpr(env, 6), env->nip);
2066 d094807b bellard
}
2067 d094807b bellard
2068 e1833e1f j_mayer
/* Note that this function should be greatly optimized
2069 e1833e1f j_mayer
 * when called with a constant excp, from ppc_hw_interrupt
2070 e1833e1f j_mayer
 */
2071 636aa200 Blue Swirl
static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2072 18fba28c bellard
{
2073 0411a972 j_mayer
    target_ulong msr, new_msr, vector;
2074 e1833e1f j_mayer
    int srr0, srr1, asrr0, asrr1;
2075 a4f30719 j_mayer
    int lpes0, lpes1, lev;
2076 79aceca5 bellard
2077 b172c56a j_mayer
    if (0) {
2078 b172c56a j_mayer
        /* XXX: find a suitable condition to enable the hypervisor mode */
2079 b172c56a j_mayer
        lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2080 b172c56a j_mayer
        lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2081 b172c56a j_mayer
    } else {
2082 b172c56a j_mayer
        /* Those values ensure we won't enter the hypervisor mode */
2083 b172c56a j_mayer
        lpes0 = 0;
2084 b172c56a j_mayer
        lpes1 = 1;
2085 b172c56a j_mayer
    }
2086 b172c56a j_mayer
2087 90e189ec Blue Swirl
    qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
2088 90e189ec Blue Swirl
                  " => %08x (%02x)\n", env->nip, excp, env->error_code);
2089 41557447 Alexander Graf
2090 41557447 Alexander Graf
    /* new srr1 value excluding must-be-zero bits */
2091 41557447 Alexander Graf
    msr = env->msr & ~0x783f0000ULL;
2092 41557447 Alexander Graf
2093 41557447 Alexander Graf
    /* new interrupt handler msr */
2094 41557447 Alexander Graf
    new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2095 41557447 Alexander Graf
2096 41557447 Alexander Graf
    /* target registers */
2097 e1833e1f j_mayer
    srr0 = SPR_SRR0;
2098 e1833e1f j_mayer
    srr1 = SPR_SRR1;
2099 e1833e1f j_mayer
    asrr0 = -1;
2100 e1833e1f j_mayer
    asrr1 = -1;
2101 41557447 Alexander Graf
2102 9a64fbe4 bellard
    switch (excp) {
2103 e1833e1f j_mayer
    case POWERPC_EXCP_NONE:
2104 e1833e1f j_mayer
        /* Should never happen */
2105 e1833e1f j_mayer
        return;
2106 e1833e1f j_mayer
    case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
2107 e1833e1f j_mayer
        switch (excp_model) {
2108 a750fc0b j_mayer
        case POWERPC_EXCP_40x:
2109 e1833e1f j_mayer
            srr0 = SPR_40x_SRR2;
2110 e1833e1f j_mayer
            srr1 = SPR_40x_SRR3;
2111 c62db105 j_mayer
            break;
2112 a750fc0b j_mayer
        case POWERPC_EXCP_BOOKE:
2113 e1833e1f j_mayer
            srr0 = SPR_BOOKE_CSRR0;
2114 e1833e1f j_mayer
            srr1 = SPR_BOOKE_CSRR1;
2115 c62db105 j_mayer
            break;
2116 e1833e1f j_mayer
        case POWERPC_EXCP_G2:
2117 c62db105 j_mayer
            break;
2118 e1833e1f j_mayer
        default:
2119 e1833e1f j_mayer
            goto excp_invalid;
2120 2be0071f bellard
        }
2121 9a64fbe4 bellard
        goto store_next;
2122 e1833e1f j_mayer
    case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
2123 e1833e1f j_mayer
        if (msr_me == 0) {
2124 e63ecc6f j_mayer
            /* Machine check exception is not enabled.
2125 e63ecc6f j_mayer
             * Enter checkstop state.
2126 e63ecc6f j_mayer
             */
2127 93fcfe39 aliguori
            if (qemu_log_enabled()) {
2128 93fcfe39 aliguori
                qemu_log("Machine check while not allowed. "
2129 e63ecc6f j_mayer
                        "Entering checkstop state\n");
2130 e63ecc6f j_mayer
            } else {
2131 e63ecc6f j_mayer
                fprintf(stderr, "Machine check while not allowed. "
2132 e63ecc6f j_mayer
                        "Entering checkstop state\n");
2133 e63ecc6f j_mayer
            }
2134 e63ecc6f j_mayer
            env->halted = 1;
2135 e63ecc6f j_mayer
            env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2136 e1833e1f j_mayer
        }
2137 b172c56a j_mayer
        if (0) {
2138 b172c56a j_mayer
            /* XXX: find a suitable condition to enable the hypervisor mode */
2139 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2140 b172c56a j_mayer
        }
2141 41557447 Alexander Graf
2142 41557447 Alexander Graf
        /* machine check exceptions don't have ME set */
2143 41557447 Alexander Graf
        new_msr &= ~((target_ulong)1 << MSR_ME);
2144 41557447 Alexander Graf
2145 e1833e1f j_mayer
        /* XXX: should also have something loaded in DAR / DSISR */
2146 e1833e1f j_mayer
        switch (excp_model) {
2147 a750fc0b j_mayer
        case POWERPC_EXCP_40x:
2148 e1833e1f j_mayer
            srr0 = SPR_40x_SRR2;
2149 e1833e1f j_mayer
            srr1 = SPR_40x_SRR3;
2150 c62db105 j_mayer
            break;
2151 a750fc0b j_mayer
        case POWERPC_EXCP_BOOKE:
2152 e1833e1f j_mayer
            srr0 = SPR_BOOKE_MCSRR0;
2153 e1833e1f j_mayer
            srr1 = SPR_BOOKE_MCSRR1;
2154 e1833e1f j_mayer
            asrr0 = SPR_BOOKE_CSRR0;
2155 e1833e1f j_mayer
            asrr1 = SPR_BOOKE_CSRR1;
2156 c62db105 j_mayer
            break;
2157 c62db105 j_mayer
        default:
2158 c62db105 j_mayer
            break;
2159 2be0071f bellard
        }
2160 e1833e1f j_mayer
        goto store_next;
2161 e1833e1f j_mayer
    case POWERPC_EXCP_DSI:       /* Data storage exception                   */
2162 90e189ec Blue Swirl
        LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2163 90e189ec Blue Swirl
                 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2164 e1833e1f j_mayer
        if (lpes1 == 0)
2165 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2166 a541f297 bellard
        goto store_next;
2167 e1833e1f j_mayer
    case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
2168 90e189ec Blue Swirl
        LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2169 90e189ec Blue Swirl
                 "\n", msr, env->nip);
2170 e1833e1f j_mayer
        if (lpes1 == 0)
2171 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2172 e1833e1f j_mayer
        msr |= env->error_code;
2173 9a64fbe4 bellard
        goto store_next;
2174 e1833e1f j_mayer
    case POWERPC_EXCP_EXTERNAL:  /* External input                           */
2175 e1833e1f j_mayer
        if (lpes0 == 1)
2176 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2177 9a64fbe4 bellard
        goto store_next;
2178 e1833e1f j_mayer
    case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
2179 e1833e1f j_mayer
        if (lpes1 == 0)
2180 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2181 e1833e1f j_mayer
        /* XXX: this is false */
2182 e1833e1f j_mayer
        /* Get rS/rD and rA from faulting opcode */
2183 e1833e1f j_mayer
        env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2184 9a64fbe4 bellard
        goto store_current;
2185 e1833e1f j_mayer
    case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
2186 9a64fbe4 bellard
        switch (env->error_code & ~0xF) {
2187 e1833e1f j_mayer
        case POWERPC_EXCP_FP:
2188 e1833e1f j_mayer
            if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2189 d12d51d5 aliguori
                LOG_EXCP("Ignore floating point exception\n");
2190 7c58044c j_mayer
                env->exception_index = POWERPC_EXCP_NONE;
2191 7c58044c j_mayer
                env->error_code = 0;
2192 9a64fbe4 bellard
                return;
2193 76a66253 j_mayer
            }
2194 e1833e1f j_mayer
            if (lpes1 == 0)
2195 a4f30719 j_mayer
                new_msr |= (target_ulong)MSR_HVB;
2196 9a64fbe4 bellard
            msr |= 0x00100000;
2197 5b52b991 j_mayer
            if (msr_fe0 == msr_fe1)
2198 5b52b991 j_mayer
                goto store_next;
2199 5b52b991 j_mayer
            msr |= 0x00010000;
2200 76a66253 j_mayer
            break;
2201 e1833e1f j_mayer
        case POWERPC_EXCP_INVAL:
2202 90e189ec Blue Swirl
            LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2203 e1833e1f j_mayer
            if (lpes1 == 0)
2204 a4f30719 j_mayer
                new_msr |= (target_ulong)MSR_HVB;
2205 9a64fbe4 bellard
            msr |= 0x00080000;
2206 76a66253 j_mayer
            break;
2207 e1833e1f j_mayer
        case POWERPC_EXCP_PRIV:
2208 e1833e1f j_mayer
            if (lpes1 == 0)
2209 a4f30719 j_mayer
                new_msr |= (target_ulong)MSR_HVB;
2210 9a64fbe4 bellard
            msr |= 0x00040000;
2211 76a66253 j_mayer
            break;
2212 e1833e1f j_mayer
        case POWERPC_EXCP_TRAP:
2213 e1833e1f j_mayer
            if (lpes1 == 0)
2214 a4f30719 j_mayer
                new_msr |= (target_ulong)MSR_HVB;
2215 9a64fbe4 bellard
            msr |= 0x00020000;
2216 9a64fbe4 bellard
            break;
2217 9a64fbe4 bellard
        default:
2218 9a64fbe4 bellard
            /* Should never occur */
2219 e1833e1f j_mayer
            cpu_abort(env, "Invalid program exception %d. Aborting\n",
2220 e1833e1f j_mayer
                      env->error_code);
2221 76a66253 j_mayer
            break;
2222 76a66253 j_mayer
        }
2223 5b52b991 j_mayer
        goto store_current;
2224 e1833e1f j_mayer
    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
2225 e1833e1f j_mayer
        if (lpes1 == 0)
2226 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2227 e1833e1f j_mayer
        goto store_current;
2228 e1833e1f j_mayer
    case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
2229 93fcfe39 aliguori
        dump_syscall(env);
2230 f9fdea6b j_mayer
        lev = env->error_code;
2231 e1833e1f j_mayer
        if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2232 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2233 e1833e1f j_mayer
        goto store_next;
2234 e1833e1f j_mayer
    case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
2235 e1833e1f j_mayer
        goto store_current;
2236 e1833e1f j_mayer
    case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
2237 e1833e1f j_mayer
        if (lpes1 == 0)
2238 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2239 e1833e1f j_mayer
        goto store_next;
2240 e1833e1f j_mayer
    case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
2241 e1833e1f j_mayer
        /* FIT on 4xx */
2242 d12d51d5 aliguori
        LOG_EXCP("FIT exception\n");
2243 9a64fbe4 bellard
        goto store_next;
2244 e1833e1f j_mayer
    case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
2245 d12d51d5 aliguori
        LOG_EXCP("WDT exception\n");
2246 e1833e1f j_mayer
        switch (excp_model) {
2247 e1833e1f j_mayer
        case POWERPC_EXCP_BOOKE:
2248 e1833e1f j_mayer
            srr0 = SPR_BOOKE_CSRR0;
2249 e1833e1f j_mayer
            srr1 = SPR_BOOKE_CSRR1;
2250 e1833e1f j_mayer
            break;
2251 e1833e1f j_mayer
        default:
2252 e1833e1f j_mayer
            break;
2253 e1833e1f j_mayer
        }
2254 2be0071f bellard
        goto store_next;
2255 e1833e1f j_mayer
    case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
2256 e1833e1f j_mayer
        goto store_next;
2257 e1833e1f j_mayer
    case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
2258 e1833e1f j_mayer
        goto store_next;
2259 e1833e1f j_mayer
    case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
2260 e1833e1f j_mayer
        switch (excp_model) {
2261 e1833e1f j_mayer
        case POWERPC_EXCP_BOOKE:
2262 e1833e1f j_mayer
            srr0 = SPR_BOOKE_DSRR0;
2263 e1833e1f j_mayer
            srr1 = SPR_BOOKE_DSRR1;
2264 e1833e1f j_mayer
            asrr0 = SPR_BOOKE_CSRR0;
2265 e1833e1f j_mayer
            asrr1 = SPR_BOOKE_CSRR1;
2266 e1833e1f j_mayer
            break;
2267 e1833e1f j_mayer
        default:
2268 e1833e1f j_mayer
            break;
2269 e1833e1f j_mayer
        }
2270 2be0071f bellard
        /* XXX: TODO */
2271 e1833e1f j_mayer
        cpu_abort(env, "Debug exception is not implemented yet !\n");
2272 2be0071f bellard
        goto store_next;
2273 e1833e1f j_mayer
    case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
2274 e1833e1f j_mayer
        goto store_current;
2275 e1833e1f j_mayer
    case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
2276 2be0071f bellard
        /* XXX: TODO */
2277 e1833e1f j_mayer
        cpu_abort(env, "Embedded floating point data exception "
2278 2be0071f bellard
                  "is not implemented yet !\n");
2279 2be0071f bellard
        goto store_next;
2280 e1833e1f j_mayer
    case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
2281 2be0071f bellard
        /* XXX: TODO */
2282 e1833e1f j_mayer
        cpu_abort(env, "Embedded floating point round exception "
2283 e1833e1f j_mayer
                  "is not implemented yet !\n");
2284 9a64fbe4 bellard
        goto store_next;
2285 e1833e1f j_mayer
    case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
2286 2be0071f bellard
        /* XXX: TODO */
2287 2be0071f bellard
        cpu_abort(env,
2288 e1833e1f j_mayer
                  "Performance counter exception is not implemented yet !\n");
2289 9a64fbe4 bellard
        goto store_next;
2290 e1833e1f j_mayer
    case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
2291 76a66253 j_mayer
        /* XXX: TODO */
2292 e1833e1f j_mayer
        cpu_abort(env,
2293 e1833e1f j_mayer
                  "Embedded doorbell interrupt is not implemented yet !\n");
2294 2be0071f bellard
        goto store_next;
2295 e1833e1f j_mayer
    case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
2296 e1833e1f j_mayer
        switch (excp_model) {
2297 e1833e1f j_mayer
        case POWERPC_EXCP_BOOKE:
2298 e1833e1f j_mayer
            srr0 = SPR_BOOKE_CSRR0;
2299 e1833e1f j_mayer
            srr1 = SPR_BOOKE_CSRR1;
2300 a750fc0b j_mayer
            break;
2301 2be0071f bellard
        default:
2302 2be0071f bellard
            break;
2303 2be0071f bellard
        }
2304 e1833e1f j_mayer
        /* XXX: TODO */
2305 e1833e1f j_mayer
        cpu_abort(env, "Embedded doorbell critical interrupt "
2306 e1833e1f j_mayer
                  "is not implemented yet !\n");
2307 e1833e1f j_mayer
        goto store_next;
2308 e1833e1f j_mayer
    case POWERPC_EXCP_RESET:     /* System reset exception                   */
2309 41557447 Alexander Graf
        if (msr_pow) {
2310 41557447 Alexander Graf
            /* indicate that we resumed from power save mode */
2311 41557447 Alexander Graf
            msr |= 0x10000;
2312 41557447 Alexander Graf
        } else {
2313 41557447 Alexander Graf
            new_msr &= ~((target_ulong)1 << MSR_ME);
2314 41557447 Alexander Graf
        }
2315 41557447 Alexander Graf
2316 a4f30719 j_mayer
        if (0) {
2317 a4f30719 j_mayer
            /* XXX: find a suitable condition to enable the hypervisor mode */
2318 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2319 a4f30719 j_mayer
        }
2320 e1833e1f j_mayer
        goto store_next;
2321 e1833e1f j_mayer
    case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
2322 e1833e1f j_mayer
        if (lpes1 == 0)
2323 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2324 e1833e1f j_mayer
        goto store_next;
2325 e1833e1f j_mayer
    case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
2326 e1833e1f j_mayer
        if (lpes1 == 0)
2327 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2328 e1833e1f j_mayer
        goto store_next;
2329 e1833e1f j_mayer
    case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
2330 e1833e1f j_mayer
        srr0 = SPR_HSRR0;
2331 f9fdea6b j_mayer
        srr1 = SPR_HSRR1;
2332 a4f30719 j_mayer
        new_msr |= (target_ulong)MSR_HVB;
2333 41557447 Alexander Graf
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2334 b172c56a j_mayer
        goto store_next;
2335 e1833e1f j_mayer
    case POWERPC_EXCP_TRACE:     /* Trace exception                          */
2336 e1833e1f j_mayer
        if (lpes1 == 0)
2337 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2338 e1833e1f j_mayer
        goto store_next;
2339 e1833e1f j_mayer
    case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
2340 e1833e1f j_mayer
        srr0 = SPR_HSRR0;
2341 f9fdea6b j_mayer
        srr1 = SPR_HSRR1;
2342 a4f30719 j_mayer
        new_msr |= (target_ulong)MSR_HVB;
2343 41557447 Alexander Graf
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2344 e1833e1f j_mayer
        goto store_next;
2345 e1833e1f j_mayer
    case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
2346 e1833e1f j_mayer
        srr0 = SPR_HSRR0;
2347 f9fdea6b j_mayer
        srr1 = SPR_HSRR1;
2348 a4f30719 j_mayer
        new_msr |= (target_ulong)MSR_HVB;
2349 41557447 Alexander Graf
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2350 e1833e1f j_mayer
        goto store_next;
2351 e1833e1f j_mayer
    case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
2352 e1833e1f j_mayer
        srr0 = SPR_HSRR0;
2353 f9fdea6b j_mayer
        srr1 = SPR_HSRR1;
2354 a4f30719 j_mayer
        new_msr |= (target_ulong)MSR_HVB;
2355 41557447 Alexander Graf
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2356 e1833e1f j_mayer
        goto store_next;
2357 e1833e1f j_mayer
    case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
2358 e1833e1f j_mayer
        srr0 = SPR_HSRR0;
2359 f9fdea6b j_mayer
        srr1 = SPR_HSRR1;
2360 a4f30719 j_mayer
        new_msr |= (target_ulong)MSR_HVB;
2361 41557447 Alexander Graf
        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2362 e1833e1f j_mayer
        goto store_next;
2363 e1833e1f j_mayer
    case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
2364 e1833e1f j_mayer
        if (lpes1 == 0)
2365 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2366 e1833e1f j_mayer
        goto store_current;
2367 e1833e1f j_mayer
    case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
2368 d12d51d5 aliguori
        LOG_EXCP("PIT exception\n");
2369 e1833e1f j_mayer
        goto store_next;
2370 e1833e1f j_mayer
    case POWERPC_EXCP_IO:        /* IO error exception                       */
2371 e1833e1f j_mayer
        /* XXX: TODO */
2372 e1833e1f j_mayer
        cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2373 e1833e1f j_mayer
        goto store_next;
2374 e1833e1f j_mayer
    case POWERPC_EXCP_RUNM:      /* Run mode exception                       */
2375 e1833e1f j_mayer
        /* XXX: TODO */
2376 e1833e1f j_mayer
        cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2377 e1833e1f j_mayer
        goto store_next;
2378 e1833e1f j_mayer
    case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 */
2379 e1833e1f j_mayer
        /* XXX: TODO */
2380 e1833e1f j_mayer
        cpu_abort(env, "602 emulation trap exception "
2381 e1833e1f j_mayer
                  "is not implemented yet !\n");
2382 e1833e1f j_mayer
        goto store_next;
2383 e1833e1f j_mayer
    case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
2384 a4f30719 j_mayer
        if (lpes1 == 0) /* XXX: check this */
2385 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2386 e1833e1f j_mayer
        switch (excp_model) {
2387 a750fc0b j_mayer
        case POWERPC_EXCP_602:
2388 a750fc0b j_mayer
        case POWERPC_EXCP_603:
2389 a750fc0b j_mayer
        case POWERPC_EXCP_603E:
2390 a750fc0b j_mayer
        case POWERPC_EXCP_G2:
2391 e1833e1f j_mayer
            goto tlb_miss_tgpr;
2392 a750fc0b j_mayer
        case POWERPC_EXCP_7x5:
2393 76a66253 j_mayer
            goto tlb_miss;
2394 7dbe11ac j_mayer
        case POWERPC_EXCP_74xx:
2395 7dbe11ac j_mayer
            goto tlb_miss_74xx;
2396 2be0071f bellard
        default:
2397 e1833e1f j_mayer
            cpu_abort(env, "Invalid instruction TLB miss exception\n");
2398 2be0071f bellard
            break;
2399 2be0071f bellard
        }
2400 e1833e1f j_mayer
        break;
2401 e1833e1f j_mayer
    case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
2402 a4f30719 j_mayer
        if (lpes1 == 0) /* XXX: check this */
2403 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2404 e1833e1f j_mayer
        switch (excp_model) {
2405 a750fc0b j_mayer
        case POWERPC_EXCP_602:
2406 a750fc0b j_mayer
        case POWERPC_EXCP_603:
2407 a750fc0b j_mayer
        case POWERPC_EXCP_603E:
2408 a750fc0b j_mayer
        case POWERPC_EXCP_G2:
2409 e1833e1f j_mayer
            goto tlb_miss_tgpr;
2410 a750fc0b j_mayer
        case POWERPC_EXCP_7x5:
2411 76a66253 j_mayer
            goto tlb_miss;
2412 7dbe11ac j_mayer
        case POWERPC_EXCP_74xx:
2413 7dbe11ac j_mayer
            goto tlb_miss_74xx;
2414 2be0071f bellard
        default:
2415 e1833e1f j_mayer
            cpu_abort(env, "Invalid data load TLB miss exception\n");
2416 2be0071f bellard
            break;
2417 2be0071f bellard
        }
2418 e1833e1f j_mayer
        break;
2419 e1833e1f j_mayer
    case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
2420 a4f30719 j_mayer
        if (lpes1 == 0) /* XXX: check this */
2421 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2422 e1833e1f j_mayer
        switch (excp_model) {
2423 a750fc0b j_mayer
        case POWERPC_EXCP_602:
2424 a750fc0b j_mayer
        case POWERPC_EXCP_603:
2425 a750fc0b j_mayer
        case POWERPC_EXCP_603E:
2426 a750fc0b j_mayer
        case POWERPC_EXCP_G2:
2427 e1833e1f j_mayer
        tlb_miss_tgpr:
2428 76a66253 j_mayer
            /* Swap temporary saved registers with GPRs */
2429 0411a972 j_mayer
            if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2430 0411a972 j_mayer
                new_msr |= (target_ulong)1 << MSR_TGPR;
2431 0411a972 j_mayer
                hreg_swap_gpr_tgpr(env);
2432 0411a972 j_mayer
            }
2433 e1833e1f j_mayer
            goto tlb_miss;
2434 e1833e1f j_mayer
        case POWERPC_EXCP_7x5:
2435 e1833e1f j_mayer
        tlb_miss:
2436 2be0071f bellard
#if defined (DEBUG_SOFTWARE_TLB)
2437 93fcfe39 aliguori
            if (qemu_log_enabled()) {
2438 0bf9e31a Blue Swirl
                const char *es;
2439 76a66253 j_mayer
                target_ulong *miss, *cmp;
2440 76a66253 j_mayer
                int en;
2441 1e6784f9 j_mayer
                if (excp == POWERPC_EXCP_IFTLB) {
2442 76a66253 j_mayer
                    es = "I";
2443 76a66253 j_mayer
                    en = 'I';
2444 76a66253 j_mayer
                    miss = &env->spr[SPR_IMISS];
2445 76a66253 j_mayer
                    cmp = &env->spr[SPR_ICMP];
2446 76a66253 j_mayer
                } else {
2447 1e6784f9 j_mayer
                    if (excp == POWERPC_EXCP_DLTLB)
2448 76a66253 j_mayer
                        es = "DL";
2449 76a66253 j_mayer
                    else
2450 76a66253 j_mayer
                        es = "DS";
2451 76a66253 j_mayer
                    en = 'D';
2452 76a66253 j_mayer
                    miss = &env->spr[SPR_DMISS];
2453 76a66253 j_mayer
                    cmp = &env->spr[SPR_DCMP];
2454 76a66253 j_mayer
                }
2455 90e189ec Blue Swirl
                qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2456 90e189ec Blue Swirl
                         TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2457 90e189ec Blue Swirl
                         TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2458 90e189ec Blue Swirl
                         env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2459 90e189ec Blue Swirl
                         env->error_code);
2460 2be0071f bellard
            }
2461 9a64fbe4 bellard
#endif
2462 2be0071f bellard
            msr |= env->crf[0] << 28;
2463 2be0071f bellard
            msr |= env->error_code; /* key, D/I, S/L bits */
2464 2be0071f bellard
            /* Set way using a LRU mechanism */
2465 76a66253 j_mayer
            msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2466 c62db105 j_mayer
            break;
2467 7dbe11ac j_mayer
        case POWERPC_EXCP_74xx:
2468 7dbe11ac j_mayer
        tlb_miss_74xx:
2469 7dbe11ac j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
2470 93fcfe39 aliguori
            if (qemu_log_enabled()) {
2471 0bf9e31a Blue Swirl
                const char *es;
2472 7dbe11ac j_mayer
                target_ulong *miss, *cmp;
2473 7dbe11ac j_mayer
                int en;
2474 7dbe11ac j_mayer
                if (excp == POWERPC_EXCP_IFTLB) {
2475 7dbe11ac j_mayer
                    es = "I";
2476 7dbe11ac j_mayer
                    en = 'I';
2477 0411a972 j_mayer
                    miss = &env->spr[SPR_TLBMISS];
2478 0411a972 j_mayer
                    cmp = &env->spr[SPR_PTEHI];
2479 7dbe11ac j_mayer
                } else {
2480 7dbe11ac j_mayer
                    if (excp == POWERPC_EXCP_DLTLB)
2481 7dbe11ac j_mayer
                        es = "DL";
2482 7dbe11ac j_mayer
                    else
2483 7dbe11ac j_mayer
                        es = "DS";
2484 7dbe11ac j_mayer
                    en = 'D';
2485 7dbe11ac j_mayer
                    miss = &env->spr[SPR_TLBMISS];
2486 7dbe11ac j_mayer
                    cmp = &env->spr[SPR_PTEHI];
2487 7dbe11ac j_mayer
                }
2488 90e189ec Blue Swirl
                qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2489 90e189ec Blue Swirl
                         TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2490 90e189ec Blue Swirl
                         env->error_code);
2491 7dbe11ac j_mayer
            }
2492 7dbe11ac j_mayer
#endif
2493 7dbe11ac j_mayer
            msr |= env->error_code; /* key bit */
2494 7dbe11ac j_mayer
            break;
2495 2be0071f bellard
        default:
2496 e1833e1f j_mayer
            cpu_abort(env, "Invalid data store TLB miss exception\n");
2497 2be0071f bellard
            break;
2498 2be0071f bellard
        }
2499 e1833e1f j_mayer
        goto store_next;
2500 e1833e1f j_mayer
    case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
2501 e1833e1f j_mayer
        /* XXX: TODO */
2502 e1833e1f j_mayer
        cpu_abort(env, "Floating point assist exception "
2503 e1833e1f j_mayer
                  "is not implemented yet !\n");
2504 e1833e1f j_mayer
        goto store_next;
2505 b4095fed j_mayer
    case POWERPC_EXCP_DABR:      /* Data address breakpoint                  */
2506 b4095fed j_mayer
        /* XXX: TODO */
2507 b4095fed j_mayer
        cpu_abort(env, "DABR exception is not implemented yet !\n");
2508 b4095fed j_mayer
        goto store_next;
2509 e1833e1f j_mayer
    case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
2510 e1833e1f j_mayer
        /* XXX: TODO */
2511 e1833e1f j_mayer
        cpu_abort(env, "IABR exception is not implemented yet !\n");
2512 e1833e1f j_mayer
        goto store_next;
2513 e1833e1f j_mayer
    case POWERPC_EXCP_SMI:       /* System management interrupt              */
2514 e1833e1f j_mayer
        /* XXX: TODO */
2515 e1833e1f j_mayer
        cpu_abort(env, "SMI exception is not implemented yet !\n");
2516 e1833e1f j_mayer
        goto store_next;
2517 e1833e1f j_mayer
    case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
2518 e1833e1f j_mayer
        /* XXX: TODO */
2519 e1833e1f j_mayer
        cpu_abort(env, "Thermal management exception "
2520 e1833e1f j_mayer
                  "is not implemented yet !\n");
2521 e1833e1f j_mayer
        goto store_next;
2522 e1833e1f j_mayer
    case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
2523 e1833e1f j_mayer
        if (lpes1 == 0)
2524 a4f30719 j_mayer
            new_msr |= (target_ulong)MSR_HVB;
2525 e1833e1f j_mayer
        /* XXX: TODO */
2526 e1833e1f j_mayer
        cpu_abort(env,
2527 e1833e1f j_mayer
                  "Performance counter exception is not implemented yet !\n");
2528 e1833e1f j_mayer
        goto store_next;
2529 e1833e1f j_mayer
    case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
2530 e1833e1f j_mayer
        /* XXX: TODO */
2531 e1833e1f j_mayer
        cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2532 e1833e1f j_mayer
        goto store_next;
2533 e1833e1f j_mayer
    case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
2534 e1833e1f j_mayer
        /* XXX: TODO */
2535 e1833e1f j_mayer
        cpu_abort(env,
2536 e1833e1f j_mayer
                  "970 soft-patch exception is not implemented yet !\n");
2537 e1833e1f j_mayer
        goto store_next;
2538 e1833e1f j_mayer
    case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
2539 e1833e1f j_mayer
        /* XXX: TODO */
2540 e1833e1f j_mayer
        cpu_abort(env,
2541 e1833e1f j_mayer
                  "970 maintenance exception is not implemented yet !\n");
2542 e1833e1f j_mayer
        goto store_next;
2543 b4095fed j_mayer
    case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             */
2544 b4095fed j_mayer
        /* XXX: TODO */
2545 b4095fed j_mayer
        cpu_abort(env, "Maskable external exception "
2546 b4095fed j_mayer
                  "is not implemented yet !\n");
2547 b4095fed j_mayer
        goto store_next;
2548 b4095fed j_mayer
    case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         */
2549 b4095fed j_mayer
        /* XXX: TODO */
2550 b4095fed j_mayer
        cpu_abort(env, "Non maskable external exception "
2551 b4095fed j_mayer
                  "is not implemented yet !\n");
2552 b4095fed j_mayer
        goto store_next;
2553 2be0071f bellard
    default:
2554 e1833e1f j_mayer
    excp_invalid:
2555 e1833e1f j_mayer
        cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2556 e1833e1f j_mayer
        break;
2557 9a64fbe4 bellard
    store_current:
2558 2be0071f bellard
        /* save current instruction location */
2559 e1833e1f j_mayer
        env->spr[srr0] = env->nip - 4;
2560 9a64fbe4 bellard
        break;
2561 9a64fbe4 bellard
    store_next:
2562 2be0071f bellard
        /* save next instruction location */
2563 e1833e1f j_mayer
        env->spr[srr0] = env->nip;
2564 9a64fbe4 bellard
        break;
2565 9a64fbe4 bellard
    }
2566 e1833e1f j_mayer
    /* Save MSR */
2567 e1833e1f j_mayer
    env->spr[srr1] = msr;
2568 e1833e1f j_mayer
    /* If any alternate SRR register are defined, duplicate saved values */
2569 e1833e1f j_mayer
    if (asrr0 != -1)
2570 e1833e1f j_mayer
        env->spr[asrr0] = env->spr[srr0];
2571 e1833e1f j_mayer
    if (asrr1 != -1)
2572 e1833e1f j_mayer
        env->spr[asrr1] = env->spr[srr1];
2573 2be0071f bellard
    /* If we disactivated any translation, flush TLBs */
2574 0411a972 j_mayer
    if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2575 2be0071f bellard
        tlb_flush(env, 1);
2576 41557447 Alexander Graf
2577 41557447 Alexander Graf
    if (msr_ile) {
2578 0411a972 j_mayer
        new_msr |= (target_ulong)1 << MSR_LE;
2579 41557447 Alexander Graf
    }
2580 41557447 Alexander Graf
2581 e1833e1f j_mayer
    /* Jump to handler */
2582 e1833e1f j_mayer
    vector = env->excp_vectors[excp];
2583 6f2d8978 j_mayer
    if (vector == (target_ulong)-1ULL) {
2584 e1833e1f j_mayer
        cpu_abort(env, "Raised an exception without defined vector %d\n",
2585 e1833e1f j_mayer
                  excp);
2586 e1833e1f j_mayer
    }
2587 e1833e1f j_mayer
    vector |= env->excp_prefix;
2588 c62db105 j_mayer
#if defined(TARGET_PPC64)
2589 e1833e1f j_mayer
    if (excp_model == POWERPC_EXCP_BOOKE) {
2590 0411a972 j_mayer
        if (!msr_icm) {
2591 e1833e1f j_mayer
            vector = (uint32_t)vector;
2592 0411a972 j_mayer
        } else {
2593 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_CM;
2594 0411a972 j_mayer
        }
2595 c62db105 j_mayer
    } else {
2596 6ce0ca12 blueswir1
        if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2597 e1833e1f j_mayer
            vector = (uint32_t)vector;
2598 0411a972 j_mayer
        } else {
2599 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_SF;
2600 0411a972 j_mayer
        }
2601 c62db105 j_mayer
    }
2602 e1833e1f j_mayer
#endif
2603 0411a972 j_mayer
    /* XXX: we don't use hreg_store_msr here as already have treated
2604 0411a972 j_mayer
     *      any special case that could occur. Just store MSR and update hflags
2605 0411a972 j_mayer
     */
2606 a4f30719 j_mayer
    env->msr = new_msr & env->msr_mask;
2607 0411a972 j_mayer
    hreg_compute_hflags(env);
2608 e1833e1f j_mayer
    env->nip = vector;
2609 e1833e1f j_mayer
    /* Reset exception state */
2610 e1833e1f j_mayer
    env->exception_index = POWERPC_EXCP_NONE;
2611 e1833e1f j_mayer
    env->error_code = 0;
2612 a586e548 Edgar E. Iglesias
2613 a586e548 Edgar E. Iglesias
    if (env->mmu_model == POWERPC_MMU_BOOKE) {
2614 a586e548 Edgar E. Iglesias
        /* XXX: The BookE changes address space when switching modes,
2615 a586e548 Edgar E. Iglesias
                we should probably implement that as different MMU indexes,
2616 a586e548 Edgar E. Iglesias
                but for the moment we do it the slow way and flush all.  */
2617 a586e548 Edgar E. Iglesias
        tlb_flush(env, 1);
2618 a586e548 Edgar E. Iglesias
    }
2619 fb0eaffc bellard
}
2620 47103572 j_mayer
2621 e1833e1f j_mayer
void do_interrupt (CPUState *env)
2622 47103572 j_mayer
{
2623 e1833e1f j_mayer
    powerpc_excp(env, env->excp_model, env->exception_index);
2624 e1833e1f j_mayer
}
2625 47103572 j_mayer
2626 e1833e1f j_mayer
void ppc_hw_interrupt (CPUPPCState *env)
2627 e1833e1f j_mayer
{
2628 f9fdea6b j_mayer
    int hdice;
2629 f9fdea6b j_mayer
2630 0411a972 j_mayer
#if 0
2631 93fcfe39 aliguori
    qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
2632 a496775f j_mayer
                __func__, env, env->pending_interrupts,
2633 0411a972 j_mayer
                env->interrupt_request, (int)msr_me, (int)msr_ee);
2634 47103572 j_mayer
#endif
2635 e1833e1f j_mayer
    /* External reset */
2636 47103572 j_mayer
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
2637 47103572 j_mayer
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
2638 e1833e1f j_mayer
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
2639 e1833e1f j_mayer
        return;
2640 e1833e1f j_mayer
    }
2641 e1833e1f j_mayer
    /* Machine check exception */
2642 e1833e1f j_mayer
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
2643 e1833e1f j_mayer
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
2644 e1833e1f j_mayer
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
2645 e1833e1f j_mayer
        return;
2646 47103572 j_mayer
    }
2647 e1833e1f j_mayer
#if 0 /* TODO */
2648 e1833e1f j_mayer
    /* External debug exception */
2649 e1833e1f j_mayer
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
2650 e1833e1f j_mayer
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2651 e1833e1f j_mayer
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
2652 e1833e1f j_mayer
        return;
2653 e1833e1f j_mayer
    }
2654 e1833e1f j_mayer
#endif
2655 b172c56a j_mayer
    if (0) {
2656 b172c56a j_mayer
        /* XXX: find a suitable condition to enable the hypervisor mode */
2657 b172c56a j_mayer
        hdice = env->spr[SPR_LPCR] & 1;
2658 b172c56a j_mayer
    } else {
2659 b172c56a j_mayer
        hdice = 0;
2660 b172c56a j_mayer
    }
2661 f9fdea6b j_mayer
    if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
2662 47103572 j_mayer
        /* Hypervisor decrementer exception */
2663 47103572 j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
2664 47103572 j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
2665 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
2666 e1833e1f j_mayer
            return;
2667 e1833e1f j_mayer
        }
2668 e1833e1f j_mayer
    }
2669 e1833e1f j_mayer
    if (msr_ce != 0) {
2670 e1833e1f j_mayer
        /* External critical interrupt */
2671 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
2672 e1833e1f j_mayer
            /* Taking a critical external interrupt does not clear the external
2673 e1833e1f j_mayer
             * critical interrupt status
2674 e1833e1f j_mayer
             */
2675 e1833e1f j_mayer
#if 0
2676 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
2677 47103572 j_mayer
#endif
2678 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
2679 e1833e1f j_mayer
            return;
2680 e1833e1f j_mayer
        }
2681 e1833e1f j_mayer
    }
2682 e1833e1f j_mayer
    if (msr_ee != 0) {
2683 e1833e1f j_mayer
        /* Watchdog timer on embedded PowerPC */
2684 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
2685 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
2686 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
2687 e1833e1f j_mayer
            return;
2688 e1833e1f j_mayer
        }
2689 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
2690 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
2691 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
2692 e1833e1f j_mayer
            return;
2693 e1833e1f j_mayer
        }
2694 e1833e1f j_mayer
        /* Fixed interval timer on embedded PowerPC */
2695 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
2696 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
2697 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
2698 e1833e1f j_mayer
            return;
2699 e1833e1f j_mayer
        }
2700 e1833e1f j_mayer
        /* Programmable interval timer on embedded PowerPC */
2701 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
2702 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
2703 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
2704 e1833e1f j_mayer
            return;
2705 e1833e1f j_mayer
        }
2706 47103572 j_mayer
        /* Decrementer exception */
2707 47103572 j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
2708 47103572 j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
2709 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
2710 e1833e1f j_mayer
            return;
2711 e1833e1f j_mayer
        }
2712 47103572 j_mayer
        /* External interrupt */
2713 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
2714 e9df014c j_mayer
            /* Taking an external interrupt does not clear the external
2715 e9df014c j_mayer
             * interrupt status
2716 e9df014c j_mayer
             */
2717 e9df014c j_mayer
#if 0
2718 47103572 j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
2719 e9df014c j_mayer
#endif
2720 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
2721 e1833e1f j_mayer
            return;
2722 e1833e1f j_mayer
        }
2723 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
2724 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2725 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
2726 e1833e1f j_mayer
            return;
2727 47103572 j_mayer
        }
2728 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
2729 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
2730 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
2731 e1833e1f j_mayer
            return;
2732 e1833e1f j_mayer
        }
2733 e1833e1f j_mayer
        /* Thermal interrupt */
2734 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
2735 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
2736 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
2737 e1833e1f j_mayer
            return;
2738 e1833e1f j_mayer
        }
2739 47103572 j_mayer
    }
2740 47103572 j_mayer
}
2741 18fba28c bellard
#endif /* !CONFIG_USER_ONLY */
2742 a496775f j_mayer
2743 4a057712 j_mayer
void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2744 4a057712 j_mayer
{
2745 90e189ec Blue Swirl
    qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
2746 90e189ec Blue Swirl
             TARGET_FMT_lx "\n", RA, msr);
2747 a496775f j_mayer
}
2748 a496775f j_mayer
2749 d84bda46 Blue Swirl
void cpu_reset(CPUPPCState *env)
2750 0a032cbe j_mayer
{
2751 0411a972 j_mayer
    target_ulong msr;
2752 0a032cbe j_mayer
2753 eca1bdf4 aliguori
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
2754 eca1bdf4 aliguori
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
2755 eca1bdf4 aliguori
        log_cpu_state(env, 0);
2756 eca1bdf4 aliguori
    }
2757 eca1bdf4 aliguori
2758 0411a972 j_mayer
    msr = (target_ulong)0;
2759 a4f30719 j_mayer
    if (0) {
2760 a4f30719 j_mayer
        /* XXX: find a suitable condition to enable the hypervisor mode */
2761 a4f30719 j_mayer
        msr |= (target_ulong)MSR_HVB;
2762 a4f30719 j_mayer
    }
2763 0411a972 j_mayer
    msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
2764 0411a972 j_mayer
    msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
2765 0411a972 j_mayer
    msr |= (target_ulong)1 << MSR_EP;
2766 0a032cbe j_mayer
#if defined (DO_SINGLE_STEP) && 0
2767 0a032cbe j_mayer
    /* Single step trace mode */
2768 0411a972 j_mayer
    msr |= (target_ulong)1 << MSR_SE;
2769 0411a972 j_mayer
    msr |= (target_ulong)1 << MSR_BE;
2770 0a032cbe j_mayer
#endif
2771 0a032cbe j_mayer
#if defined(CONFIG_USER_ONLY)
2772 0411a972 j_mayer
    msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
2773 4c2ab988 aurel32
    msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
2774 4c2ab988 aurel32
    msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
2775 0411a972 j_mayer
    msr |= (target_ulong)1 << MSR_PR;
2776 0a032cbe j_mayer
#else
2777 fc1c67bc Blue Swirl
    env->excp_prefix = env->hreset_excp_prefix;
2778 1c27f8fb j_mayer
    env->nip = env->hreset_vector | env->excp_prefix;
2779 b4095fed j_mayer
    if (env->mmu_model != POWERPC_MMU_REAL)
2780 141c8ae2 j_mayer
        ppc_tlb_invalidate_all(env);
2781 0a032cbe j_mayer
#endif
2782 07c485ce blueswir1
    env->msr = msr & env->msr_mask;
2783 6ce0ca12 blueswir1
#if defined(TARGET_PPC64)
2784 6ce0ca12 blueswir1
    if (env->mmu_model & POWERPC_MMU_64)
2785 6ce0ca12 blueswir1
        env->msr |= (1ULL << MSR_SF);
2786 6ce0ca12 blueswir1
#endif
2787 0411a972 j_mayer
    hreg_compute_hflags(env);
2788 18b21a2f Nathan Froyd
    env->reserve_addr = (target_ulong)-1ULL;
2789 5eb7995e j_mayer
    /* Be sure no exception or interrupt is pending */
2790 5eb7995e j_mayer
    env->pending_interrupts = 0;
2791 e1833e1f j_mayer
    env->exception_index = POWERPC_EXCP_NONE;
2792 e1833e1f j_mayer
    env->error_code = 0;
2793 5eb7995e j_mayer
    /* Flush all TLBs */
2794 5eb7995e j_mayer
    tlb_flush(env, 1);
2795 0a032cbe j_mayer
}
2796 0a032cbe j_mayer
2797 aaed909a bellard
CPUPPCState *cpu_ppc_init (const char *cpu_model)
2798 0a032cbe j_mayer
{
2799 0a032cbe j_mayer
    CPUPPCState *env;
2800 c227f099 Anthony Liguori
    const ppc_def_t *def;
2801 aaed909a bellard
2802 aaed909a bellard
    def = cpu_ppc_find_by_name(cpu_model);
2803 aaed909a bellard
    if (!def)
2804 aaed909a bellard
        return NULL;
2805 0a032cbe j_mayer
2806 0a032cbe j_mayer
    env = qemu_mallocz(sizeof(CPUPPCState));
2807 0a032cbe j_mayer
    cpu_exec_init(env);
2808 2e70f6ef pbrook
    ppc_translate_init();
2809 01ba9816 ths
    env->cpu_model_str = cpu_model;
2810 aaed909a bellard
    cpu_ppc_register_internal(env, def);
2811 d76d1650 aurel32
2812 0bf46a40 aliguori
    qemu_init_vcpu(env);
2813 d76d1650 aurel32
2814 0a032cbe j_mayer
    return env;
2815 0a032cbe j_mayer
}
2816 0a032cbe j_mayer
2817 0a032cbe j_mayer
void cpu_ppc_close (CPUPPCState *env)
2818 0a032cbe j_mayer
{
2819 0a032cbe j_mayer
    /* Should also remove all opcode tables... */
2820 aaed909a bellard
    qemu_free(env);
2821 0a032cbe j_mayer
}