Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ c48c6522

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