Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ decb4714

History | View | Annotate | Download (97 kB)

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