Statistics
| Branch: | Revision:

root / target-ppc / mmu_helper.c @ f1ff0e89

History | View | Annotate | Download (84.8 kB)

1 ec19c4d1 Blue Swirl
/*
2 ec19c4d1 Blue Swirl
 *  PowerPC MMU, TLB, SLB and BAT emulation helpers for QEMU.
3 ec19c4d1 Blue Swirl
 *
4 ec19c4d1 Blue Swirl
 *  Copyright (c) 2003-2007 Jocelyn Mayer
5 ec19c4d1 Blue Swirl
 *
6 ec19c4d1 Blue Swirl
 * This library is free software; you can redistribute it and/or
7 ec19c4d1 Blue Swirl
 * modify it under the terms of the GNU Lesser General Public
8 ec19c4d1 Blue Swirl
 * License as published by the Free Software Foundation; either
9 ec19c4d1 Blue Swirl
 * version 2 of the License, or (at your option) any later version.
10 ec19c4d1 Blue Swirl
 *
11 ec19c4d1 Blue Swirl
 * This library is distributed in the hope that it will be useful,
12 ec19c4d1 Blue Swirl
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ec19c4d1 Blue Swirl
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ec19c4d1 Blue Swirl
 * Lesser General Public License for more details.
15 ec19c4d1 Blue Swirl
 *
16 ec19c4d1 Blue Swirl
 * You should have received a copy of the GNU Lesser General Public
17 ec19c4d1 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 ec19c4d1 Blue Swirl
 */
19 ec19c4d1 Blue Swirl
#include "cpu.h"
20 ec19c4d1 Blue Swirl
#include "helper.h"
21 9c17d615 Paolo Bonzini
#include "sysemu/kvm.h"
22 8cbbe385 Blue Swirl
#include "kvm_ppc.h"
23 10b46525 David Gibson
#include "mmu-hash64.h"
24 9d7c3f4a David Gibson
#include "mmu-hash32.h"
25 ec19c4d1 Blue Swirl
26 8cbbe385 Blue Swirl
//#define DEBUG_MMU
27 8cbbe385 Blue Swirl
//#define DEBUG_BATS
28 ec19c4d1 Blue Swirl
//#define DEBUG_SOFTWARE_TLB
29 8cbbe385 Blue Swirl
//#define DUMP_PAGE_TABLES
30 8cbbe385 Blue Swirl
//#define DEBUG_SOFTWARE_TLB
31 8cbbe385 Blue Swirl
//#define FLUSH_ALL_TLBS
32 8cbbe385 Blue Swirl
33 8cbbe385 Blue Swirl
#ifdef DEBUG_MMU
34 8cbbe385 Blue Swirl
#  define LOG_MMU(...) qemu_log(__VA_ARGS__)
35 8cbbe385 Blue Swirl
#  define LOG_MMU_STATE(env) log_cpu_state((env), 0)
36 8cbbe385 Blue Swirl
#else
37 8cbbe385 Blue Swirl
#  define LOG_MMU(...) do { } while (0)
38 8cbbe385 Blue Swirl
#  define LOG_MMU_STATE(...) do { } while (0)
39 8cbbe385 Blue Swirl
#endif
40 ec19c4d1 Blue Swirl
41 ec19c4d1 Blue Swirl
#ifdef DEBUG_SOFTWARE_TLB
42 ec19c4d1 Blue Swirl
#  define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
43 ec19c4d1 Blue Swirl
#else
44 ec19c4d1 Blue Swirl
#  define LOG_SWTLB(...) do { } while (0)
45 ec19c4d1 Blue Swirl
#endif
46 ec19c4d1 Blue Swirl
47 8cbbe385 Blue Swirl
#ifdef DEBUG_BATS
48 8cbbe385 Blue Swirl
#  define LOG_BATS(...) qemu_log(__VA_ARGS__)
49 8cbbe385 Blue Swirl
#else
50 8cbbe385 Blue Swirl
#  define LOG_BATS(...) do { } while (0)
51 8cbbe385 Blue Swirl
#endif
52 8cbbe385 Blue Swirl
53 8cbbe385 Blue Swirl
/*****************************************************************************/
54 8cbbe385 Blue Swirl
/* PowerPC MMU emulation */
55 5dc68eb0 David Gibson
56 5dc68eb0 David Gibson
/* Context used internally during MMU translations */
57 5dc68eb0 David Gibson
typedef struct mmu_ctx_t mmu_ctx_t;
58 5dc68eb0 David Gibson
struct mmu_ctx_t {
59 5dc68eb0 David Gibson
    hwaddr raddr;      /* Real address              */
60 5dc68eb0 David Gibson
    hwaddr eaddr;      /* Effective address         */
61 5dc68eb0 David Gibson
    int prot;                      /* Protection bits           */
62 5dc68eb0 David Gibson
    hwaddr hash[2];    /* Pagetable hash values     */
63 5dc68eb0 David Gibson
    target_ulong ptem;             /* Virtual segment ID | API  */
64 5dc68eb0 David Gibson
    int key;                       /* Access key                */
65 5dc68eb0 David Gibson
    int nx;                        /* Non-execute area          */
66 5dc68eb0 David Gibson
};
67 5dc68eb0 David Gibson
68 8cbbe385 Blue Swirl
/* Common routines used by software and hardware TLBs emulation */
69 8cbbe385 Blue Swirl
static inline int pte_is_valid(target_ulong pte0)
70 8cbbe385 Blue Swirl
{
71 8cbbe385 Blue Swirl
    return pte0 & 0x80000000 ? 1 : 0;
72 8cbbe385 Blue Swirl
}
73 8cbbe385 Blue Swirl
74 8cbbe385 Blue Swirl
static inline void pte_invalidate(target_ulong *pte0)
75 8cbbe385 Blue Swirl
{
76 8cbbe385 Blue Swirl
    *pte0 &= ~0x80000000;
77 8cbbe385 Blue Swirl
}
78 8cbbe385 Blue Swirl
79 8cbbe385 Blue Swirl
#define PTE_PTEM_MASK 0x7FFFFFBF
80 8cbbe385 Blue Swirl
#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
81 8cbbe385 Blue Swirl
82 496272a7 David Gibson
static int pp_check(int key, int pp, int nx)
83 8cbbe385 Blue Swirl
{
84 8cbbe385 Blue Swirl
    int access;
85 8cbbe385 Blue Swirl
86 8cbbe385 Blue Swirl
    /* Compute access rights */
87 8cbbe385 Blue Swirl
    access = 0;
88 8cbbe385 Blue Swirl
    if (key == 0) {
89 8cbbe385 Blue Swirl
        switch (pp) {
90 8cbbe385 Blue Swirl
        case 0x0:
91 8cbbe385 Blue Swirl
        case 0x1:
92 8cbbe385 Blue Swirl
        case 0x2:
93 8cbbe385 Blue Swirl
            access |= PAGE_WRITE;
94 8cbbe385 Blue Swirl
            /* No break here */
95 8cbbe385 Blue Swirl
        case 0x3:
96 8cbbe385 Blue Swirl
            access |= PAGE_READ;
97 8cbbe385 Blue Swirl
            break;
98 8cbbe385 Blue Swirl
        }
99 8cbbe385 Blue Swirl
    } else {
100 8cbbe385 Blue Swirl
        switch (pp) {
101 8cbbe385 Blue Swirl
        case 0x0:
102 8cbbe385 Blue Swirl
            access = 0;
103 8cbbe385 Blue Swirl
            break;
104 8cbbe385 Blue Swirl
        case 0x1:
105 8cbbe385 Blue Swirl
        case 0x3:
106 8cbbe385 Blue Swirl
            access = PAGE_READ;
107 8cbbe385 Blue Swirl
            break;
108 8cbbe385 Blue Swirl
        case 0x2:
109 8cbbe385 Blue Swirl
            access = PAGE_READ | PAGE_WRITE;
110 8cbbe385 Blue Swirl
            break;
111 8cbbe385 Blue Swirl
        }
112 8cbbe385 Blue Swirl
    }
113 8cbbe385 Blue Swirl
    if (nx == 0) {
114 8cbbe385 Blue Swirl
        access |= PAGE_EXEC;
115 8cbbe385 Blue Swirl
    }
116 8cbbe385 Blue Swirl
117 8cbbe385 Blue Swirl
    return access;
118 8cbbe385 Blue Swirl
}
119 8cbbe385 Blue Swirl
120 496272a7 David Gibson
static int check_prot(int prot, int rw, int access_type)
121 8cbbe385 Blue Swirl
{
122 8cbbe385 Blue Swirl
    int ret;
123 8cbbe385 Blue Swirl
124 8cbbe385 Blue Swirl
    if (access_type == ACCESS_CODE) {
125 8cbbe385 Blue Swirl
        if (prot & PAGE_EXEC) {
126 8cbbe385 Blue Swirl
            ret = 0;
127 8cbbe385 Blue Swirl
        } else {
128 8cbbe385 Blue Swirl
            ret = -2;
129 8cbbe385 Blue Swirl
        }
130 8cbbe385 Blue Swirl
    } else if (rw) {
131 8cbbe385 Blue Swirl
        if (prot & PAGE_WRITE) {
132 8cbbe385 Blue Swirl
            ret = 0;
133 8cbbe385 Blue Swirl
        } else {
134 8cbbe385 Blue Swirl
            ret = -2;
135 8cbbe385 Blue Swirl
        }
136 8cbbe385 Blue Swirl
    } else {
137 8cbbe385 Blue Swirl
        if (prot & PAGE_READ) {
138 8cbbe385 Blue Swirl
            ret = 0;
139 8cbbe385 Blue Swirl
        } else {
140 8cbbe385 Blue Swirl
            ret = -2;
141 8cbbe385 Blue Swirl
        }
142 8cbbe385 Blue Swirl
    }
143 8cbbe385 Blue Swirl
144 8cbbe385 Blue Swirl
    return ret;
145 8cbbe385 Blue Swirl
}
146 8cbbe385 Blue Swirl
147 9d7c3f4a David Gibson
static inline int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
148 9d7c3f4a David Gibson
                                       target_ulong pte1, int h, int rw, int type)
149 8cbbe385 Blue Swirl
{
150 8cbbe385 Blue Swirl
    target_ulong ptem, mmask;
151 8cbbe385 Blue Swirl
    int access, ret, pteh, ptev, pp;
152 8cbbe385 Blue Swirl
153 8cbbe385 Blue Swirl
    ret = -1;
154 8cbbe385 Blue Swirl
    /* Check validity and table match */
155 9d7c3f4a David Gibson
    ptev = pte_is_valid(pte0);
156 9d7c3f4a David Gibson
    pteh = (pte0 >> 6) & 1;
157 8cbbe385 Blue Swirl
    if (ptev && h == pteh) {
158 8cbbe385 Blue Swirl
        /* Check vsid & api */
159 9d7c3f4a David Gibson
        ptem = pte0 & PTE_PTEM_MASK;
160 9d7c3f4a David Gibson
        mmask = PTE_CHECK_MASK;
161 9d7c3f4a David Gibson
        pp = pte1 & 0x00000003;
162 8cbbe385 Blue Swirl
        if (ptem == ctx->ptem) {
163 a8170e5e Avi Kivity
            if (ctx->raddr != (hwaddr)-1ULL) {
164 8cbbe385 Blue Swirl
                /* all matches should have equal RPN, WIMG & PP */
165 8cbbe385 Blue Swirl
                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
166 8cbbe385 Blue Swirl
                    qemu_log("Bad RPN/WIMG/PP\n");
167 8cbbe385 Blue Swirl
                    return -3;
168 8cbbe385 Blue Swirl
                }
169 8cbbe385 Blue Swirl
            }
170 8cbbe385 Blue Swirl
            /* Compute access rights */
171 8cbbe385 Blue Swirl
            access = pp_check(ctx->key, pp, ctx->nx);
172 8cbbe385 Blue Swirl
            /* Keep the matching PTE informations */
173 8cbbe385 Blue Swirl
            ctx->raddr = pte1;
174 8cbbe385 Blue Swirl
            ctx->prot = access;
175 8cbbe385 Blue Swirl
            ret = check_prot(ctx->prot, rw, type);
176 8cbbe385 Blue Swirl
            if (ret == 0) {
177 8cbbe385 Blue Swirl
                /* Access granted */
178 8cbbe385 Blue Swirl
                LOG_MMU("PTE access granted !\n");
179 8cbbe385 Blue Swirl
            } else {
180 8cbbe385 Blue Swirl
                /* Access right violation */
181 8cbbe385 Blue Swirl
                LOG_MMU("PTE access rejected\n");
182 8cbbe385 Blue Swirl
            }
183 8cbbe385 Blue Swirl
        }
184 8cbbe385 Blue Swirl
    }
185 8cbbe385 Blue Swirl
186 8cbbe385 Blue Swirl
    return ret;
187 8cbbe385 Blue Swirl
}
188 8cbbe385 Blue Swirl
189 496272a7 David Gibson
static int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
190 496272a7 David Gibson
                            int ret, int rw)
191 8cbbe385 Blue Swirl
{
192 8cbbe385 Blue Swirl
    int store = 0;
193 8cbbe385 Blue Swirl
194 8cbbe385 Blue Swirl
    /* Update page flags */
195 8cbbe385 Blue Swirl
    if (!(*pte1p & 0x00000100)) {
196 8cbbe385 Blue Swirl
        /* Update accessed flag */
197 8cbbe385 Blue Swirl
        *pte1p |= 0x00000100;
198 8cbbe385 Blue Swirl
        store = 1;
199 8cbbe385 Blue Swirl
    }
200 8cbbe385 Blue Swirl
    if (!(*pte1p & 0x00000080)) {
201 8cbbe385 Blue Swirl
        if (rw == 1 && ret == 0) {
202 8cbbe385 Blue Swirl
            /* Update changed flag */
203 8cbbe385 Blue Swirl
            *pte1p |= 0x00000080;
204 8cbbe385 Blue Swirl
            store = 1;
205 8cbbe385 Blue Swirl
        } else {
206 8cbbe385 Blue Swirl
            /* Force page fault for first write access */
207 8cbbe385 Blue Swirl
            ctx->prot &= ~PAGE_WRITE;
208 8cbbe385 Blue Swirl
        }
209 8cbbe385 Blue Swirl
    }
210 8cbbe385 Blue Swirl
211 8cbbe385 Blue Swirl
    return store;
212 8cbbe385 Blue Swirl
}
213 8cbbe385 Blue Swirl
214 8cbbe385 Blue Swirl
/* Software driven TLB helpers */
215 8cbbe385 Blue Swirl
static inline int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
216 8cbbe385 Blue Swirl
                                    int way, int is_code)
217 8cbbe385 Blue Swirl
{
218 8cbbe385 Blue Swirl
    int nr;
219 8cbbe385 Blue Swirl
220 8cbbe385 Blue Swirl
    /* Select TLB num in a way from address */
221 8cbbe385 Blue Swirl
    nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
222 8cbbe385 Blue Swirl
    /* Select TLB way */
223 8cbbe385 Blue Swirl
    nr += env->tlb_per_way * way;
224 8cbbe385 Blue Swirl
    /* 6xx have separate TLBs for instructions and data */
225 8cbbe385 Blue Swirl
    if (is_code && env->id_tlbs == 1) {
226 8cbbe385 Blue Swirl
        nr += env->nb_tlb;
227 8cbbe385 Blue Swirl
    }
228 8cbbe385 Blue Swirl
229 8cbbe385 Blue Swirl
    return nr;
230 8cbbe385 Blue Swirl
}
231 8cbbe385 Blue Swirl
232 8cbbe385 Blue Swirl
static inline void ppc6xx_tlb_invalidate_all(CPUPPCState *env)
233 8cbbe385 Blue Swirl
{
234 8cbbe385 Blue Swirl
    ppc6xx_tlb_t *tlb;
235 8cbbe385 Blue Swirl
    int nr, max;
236 8cbbe385 Blue Swirl
237 8cbbe385 Blue Swirl
    /* LOG_SWTLB("Invalidate all TLBs\n"); */
238 8cbbe385 Blue Swirl
    /* Invalidate all defined software TLB */
239 8cbbe385 Blue Swirl
    max = env->nb_tlb;
240 8cbbe385 Blue Swirl
    if (env->id_tlbs == 1) {
241 8cbbe385 Blue Swirl
        max *= 2;
242 8cbbe385 Blue Swirl
    }
243 8cbbe385 Blue Swirl
    for (nr = 0; nr < max; nr++) {
244 8cbbe385 Blue Swirl
        tlb = &env->tlb.tlb6[nr];
245 8cbbe385 Blue Swirl
        pte_invalidate(&tlb->pte0);
246 8cbbe385 Blue Swirl
    }
247 8cbbe385 Blue Swirl
    tlb_flush(env, 1);
248 8cbbe385 Blue Swirl
}
249 8cbbe385 Blue Swirl
250 8cbbe385 Blue Swirl
static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState *env,
251 8cbbe385 Blue Swirl
                                               target_ulong eaddr,
252 8cbbe385 Blue Swirl
                                               int is_code, int match_epn)
253 8cbbe385 Blue Swirl
{
254 8cbbe385 Blue Swirl
#if !defined(FLUSH_ALL_TLBS)
255 8cbbe385 Blue Swirl
    ppc6xx_tlb_t *tlb;
256 8cbbe385 Blue Swirl
    int way, nr;
257 8cbbe385 Blue Swirl
258 8cbbe385 Blue Swirl
    /* Invalidate ITLB + DTLB, all ways */
259 8cbbe385 Blue Swirl
    for (way = 0; way < env->nb_ways; way++) {
260 8cbbe385 Blue Swirl
        nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
261 8cbbe385 Blue Swirl
        tlb = &env->tlb.tlb6[nr];
262 8cbbe385 Blue Swirl
        if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
263 8cbbe385 Blue Swirl
            LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
264 8cbbe385 Blue Swirl
                      env->nb_tlb, eaddr);
265 8cbbe385 Blue Swirl
            pte_invalidate(&tlb->pte0);
266 8cbbe385 Blue Swirl
            tlb_flush_page(env, tlb->EPN);
267 8cbbe385 Blue Swirl
        }
268 8cbbe385 Blue Swirl
    }
269 8cbbe385 Blue Swirl
#else
270 8cbbe385 Blue Swirl
    /* XXX: PowerPC specification say this is valid as well */
271 8cbbe385 Blue Swirl
    ppc6xx_tlb_invalidate_all(env);
272 8cbbe385 Blue Swirl
#endif
273 8cbbe385 Blue Swirl
}
274 8cbbe385 Blue Swirl
275 8cbbe385 Blue Swirl
static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState *env,
276 8cbbe385 Blue Swirl
                                              target_ulong eaddr, int is_code)
277 8cbbe385 Blue Swirl
{
278 8cbbe385 Blue Swirl
    ppc6xx_tlb_invalidate_virt2(env, eaddr, is_code, 0);
279 8cbbe385 Blue Swirl
}
280 8cbbe385 Blue Swirl
281 9aa5b158 Blue Swirl
static void ppc6xx_tlb_store(CPUPPCState *env, target_ulong EPN, int way,
282 9aa5b158 Blue Swirl
                             int is_code, target_ulong pte0, target_ulong pte1)
283 8cbbe385 Blue Swirl
{
284 8cbbe385 Blue Swirl
    ppc6xx_tlb_t *tlb;
285 8cbbe385 Blue Swirl
    int nr;
286 8cbbe385 Blue Swirl
287 8cbbe385 Blue Swirl
    nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
288 8cbbe385 Blue Swirl
    tlb = &env->tlb.tlb6[nr];
289 8cbbe385 Blue Swirl
    LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
290 8cbbe385 Blue Swirl
              " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
291 8cbbe385 Blue Swirl
    /* Invalidate any pending reference in QEMU for this virtual address */
292 8cbbe385 Blue Swirl
    ppc6xx_tlb_invalidate_virt2(env, EPN, is_code, 1);
293 8cbbe385 Blue Swirl
    tlb->pte0 = pte0;
294 8cbbe385 Blue Swirl
    tlb->pte1 = pte1;
295 8cbbe385 Blue Swirl
    tlb->EPN = EPN;
296 8cbbe385 Blue Swirl
    /* Store last way for LRU mechanism */
297 8cbbe385 Blue Swirl
    env->last_way = way;
298 8cbbe385 Blue Swirl
}
299 8cbbe385 Blue Swirl
300 8cbbe385 Blue Swirl
static inline int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
301 8cbbe385 Blue Swirl
                                   target_ulong eaddr, int rw, int access_type)
302 8cbbe385 Blue Swirl
{
303 8cbbe385 Blue Swirl
    ppc6xx_tlb_t *tlb;
304 8cbbe385 Blue Swirl
    int nr, best, way;
305 8cbbe385 Blue Swirl
    int ret;
306 8cbbe385 Blue Swirl
307 8cbbe385 Blue Swirl
    best = -1;
308 8cbbe385 Blue Swirl
    ret = -1; /* No TLB found */
309 8cbbe385 Blue Swirl
    for (way = 0; way < env->nb_ways; way++) {
310 8cbbe385 Blue Swirl
        nr = ppc6xx_tlb_getnum(env, eaddr, way,
311 8cbbe385 Blue Swirl
                               access_type == ACCESS_CODE ? 1 : 0);
312 8cbbe385 Blue Swirl
        tlb = &env->tlb.tlb6[nr];
313 8cbbe385 Blue Swirl
        /* This test "emulates" the PTE index match for hardware TLBs */
314 8cbbe385 Blue Swirl
        if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
315 8cbbe385 Blue Swirl
            LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
316 8cbbe385 Blue Swirl
                      "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb,
317 8cbbe385 Blue Swirl
                      pte_is_valid(tlb->pte0) ? "valid" : "inval",
318 8cbbe385 Blue Swirl
                      tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
319 8cbbe385 Blue Swirl
            continue;
320 8cbbe385 Blue Swirl
        }
321 8cbbe385 Blue Swirl
        LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " "
322 8cbbe385 Blue Swirl
                  TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb,
323 8cbbe385 Blue Swirl
                  pte_is_valid(tlb->pte0) ? "valid" : "inval",
324 8cbbe385 Blue Swirl
                  tlb->EPN, eaddr, tlb->pte1,
325 8cbbe385 Blue Swirl
                  rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
326 9d7c3f4a David Gibson
        switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
327 8cbbe385 Blue Swirl
        case -3:
328 8cbbe385 Blue Swirl
            /* TLB inconsistency */
329 8cbbe385 Blue Swirl
            return -1;
330 8cbbe385 Blue Swirl
        case -2:
331 8cbbe385 Blue Swirl
            /* Access violation */
332 8cbbe385 Blue Swirl
            ret = -2;
333 8cbbe385 Blue Swirl
            best = nr;
334 8cbbe385 Blue Swirl
            break;
335 8cbbe385 Blue Swirl
        case -1:
336 8cbbe385 Blue Swirl
        default:
337 8cbbe385 Blue Swirl
            /* No match */
338 8cbbe385 Blue Swirl
            break;
339 8cbbe385 Blue Swirl
        case 0:
340 8cbbe385 Blue Swirl
            /* access granted */
341 8cbbe385 Blue Swirl
            /* XXX: we should go on looping to check all TLBs consistency
342 8cbbe385 Blue Swirl
             *      but we can speed-up the whole thing as the
343 8cbbe385 Blue Swirl
             *      result would be undefined if TLBs are not consistent.
344 8cbbe385 Blue Swirl
             */
345 8cbbe385 Blue Swirl
            ret = 0;
346 8cbbe385 Blue Swirl
            best = nr;
347 8cbbe385 Blue Swirl
            goto done;
348 8cbbe385 Blue Swirl
        }
349 8cbbe385 Blue Swirl
    }
350 8cbbe385 Blue Swirl
    if (best != -1) {
351 8cbbe385 Blue Swirl
    done:
352 8cbbe385 Blue Swirl
        LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
353 8cbbe385 Blue Swirl
                  ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
354 8cbbe385 Blue Swirl
        /* Update page flags */
355 8cbbe385 Blue Swirl
        pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, rw);
356 8cbbe385 Blue Swirl
    }
357 8cbbe385 Blue Swirl
358 8cbbe385 Blue Swirl
    return ret;
359 8cbbe385 Blue Swirl
}
360 8cbbe385 Blue Swirl
361 8cbbe385 Blue Swirl
/* Perform BAT hit & translation */
362 8cbbe385 Blue Swirl
static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp,
363 8cbbe385 Blue Swirl
                                 int *validp, int *protp, target_ulong *BATu,
364 8cbbe385 Blue Swirl
                                 target_ulong *BATl)
365 8cbbe385 Blue Swirl
{
366 8cbbe385 Blue Swirl
    target_ulong bl;
367 8cbbe385 Blue Swirl
    int pp, valid, prot;
368 8cbbe385 Blue Swirl
369 8cbbe385 Blue Swirl
    bl = (*BATu & 0x00001FFC) << 15;
370 8cbbe385 Blue Swirl
    valid = 0;
371 8cbbe385 Blue Swirl
    prot = 0;
372 8cbbe385 Blue Swirl
    if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
373 8cbbe385 Blue Swirl
        ((msr_pr != 0) && (*BATu & 0x00000001))) {
374 8cbbe385 Blue Swirl
        valid = 1;
375 8cbbe385 Blue Swirl
        pp = *BATl & 0x00000003;
376 8cbbe385 Blue Swirl
        if (pp != 0) {
377 8cbbe385 Blue Swirl
            prot = PAGE_READ | PAGE_EXEC;
378 8cbbe385 Blue Swirl
            if (pp == 0x2) {
379 8cbbe385 Blue Swirl
                prot |= PAGE_WRITE;
380 8cbbe385 Blue Swirl
            }
381 8cbbe385 Blue Swirl
        }
382 8cbbe385 Blue Swirl
    }
383 8cbbe385 Blue Swirl
    *blp = bl;
384 8cbbe385 Blue Swirl
    *validp = valid;
385 8cbbe385 Blue Swirl
    *protp = prot;
386 8cbbe385 Blue Swirl
}
387 8cbbe385 Blue Swirl
388 98132796 David Gibson
static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
389 98132796 David Gibson
                           target_ulong virtual, int rw, int type)
390 8cbbe385 Blue Swirl
{
391 8cbbe385 Blue Swirl
    target_ulong *BATlt, *BATut, *BATu, *BATl;
392 8cbbe385 Blue Swirl
    target_ulong BEPIl, BEPIu, bl;
393 8cbbe385 Blue Swirl
    int i, valid, prot;
394 8cbbe385 Blue Swirl
    int ret = -1;
395 8cbbe385 Blue Swirl
396 8cbbe385 Blue Swirl
    LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
397 8cbbe385 Blue Swirl
             type == ACCESS_CODE ? 'I' : 'D', virtual);
398 8cbbe385 Blue Swirl
    switch (type) {
399 8cbbe385 Blue Swirl
    case ACCESS_CODE:
400 8cbbe385 Blue Swirl
        BATlt = env->IBAT[1];
401 8cbbe385 Blue Swirl
        BATut = env->IBAT[0];
402 8cbbe385 Blue Swirl
        break;
403 8cbbe385 Blue Swirl
    default:
404 8cbbe385 Blue Swirl
        BATlt = env->DBAT[1];
405 8cbbe385 Blue Swirl
        BATut = env->DBAT[0];
406 8cbbe385 Blue Swirl
        break;
407 8cbbe385 Blue Swirl
    }
408 8cbbe385 Blue Swirl
    for (i = 0; i < env->nb_BATs; i++) {
409 8cbbe385 Blue Swirl
        BATu = &BATut[i];
410 8cbbe385 Blue Swirl
        BATl = &BATlt[i];
411 8cbbe385 Blue Swirl
        BEPIu = *BATu & 0xF0000000;
412 8cbbe385 Blue Swirl
        BEPIl = *BATu & 0x0FFE0000;
413 98132796 David Gibson
        bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
414 8cbbe385 Blue Swirl
        LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
415 8cbbe385 Blue Swirl
                 " BATl " TARGET_FMT_lx "\n", __func__,
416 8cbbe385 Blue Swirl
                 type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
417 8cbbe385 Blue Swirl
        if ((virtual & 0xF0000000) == BEPIu &&
418 8cbbe385 Blue Swirl
            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
419 8cbbe385 Blue Swirl
            /* BAT matches */
420 8cbbe385 Blue Swirl
            if (valid != 0) {
421 8cbbe385 Blue Swirl
                /* Get physical address */
422 8cbbe385 Blue Swirl
                ctx->raddr = (*BATl & 0xF0000000) |
423 8cbbe385 Blue Swirl
                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
424 8cbbe385 Blue Swirl
                    (virtual & 0x0001F000);
425 8cbbe385 Blue Swirl
                /* Compute access rights */
426 8cbbe385 Blue Swirl
                ctx->prot = prot;
427 8cbbe385 Blue Swirl
                ret = check_prot(ctx->prot, rw, type);
428 8cbbe385 Blue Swirl
                if (ret == 0) {
429 8cbbe385 Blue Swirl
                    LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
430 8cbbe385 Blue Swirl
                             i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
431 8cbbe385 Blue Swirl
                             ctx->prot & PAGE_WRITE ? 'W' : '-');
432 8cbbe385 Blue Swirl
                }
433 8cbbe385 Blue Swirl
                break;
434 8cbbe385 Blue Swirl
            }
435 8cbbe385 Blue Swirl
        }
436 8cbbe385 Blue Swirl
    }
437 8cbbe385 Blue Swirl
    if (ret < 0) {
438 8cbbe385 Blue Swirl
#if defined(DEBUG_BATS)
439 8cbbe385 Blue Swirl
        if (qemu_log_enabled()) {
440 8cbbe385 Blue Swirl
            LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
441 8cbbe385 Blue Swirl
            for (i = 0; i < 4; i++) {
442 8cbbe385 Blue Swirl
                BATu = &BATut[i];
443 8cbbe385 Blue Swirl
                BATl = &BATlt[i];
444 8cbbe385 Blue Swirl
                BEPIu = *BATu & 0xF0000000;
445 8cbbe385 Blue Swirl
                BEPIl = *BATu & 0x0FFE0000;
446 8cbbe385 Blue Swirl
                bl = (*BATu & 0x00001FFC) << 15;
447 8cbbe385 Blue Swirl
                LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
448 8cbbe385 Blue Swirl
                         " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
449 8cbbe385 Blue Swirl
                         TARGET_FMT_lx " " TARGET_FMT_lx "\n",
450 8cbbe385 Blue Swirl
                         __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
451 8cbbe385 Blue Swirl
                         *BATu, *BATl, BEPIu, BEPIl, bl);
452 8cbbe385 Blue Swirl
            }
453 8cbbe385 Blue Swirl
        }
454 8cbbe385 Blue Swirl
#endif
455 8cbbe385 Blue Swirl
    }
456 8cbbe385 Blue Swirl
    /* No hit */
457 8cbbe385 Blue Swirl
    return ret;
458 8cbbe385 Blue Swirl
}
459 8cbbe385 Blue Swirl
460 8cbbe385 Blue Swirl
/* Perform segment based translation */
461 0480884f David Gibson
static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
462 0480884f David Gibson
                                      target_ulong eaddr, int rw, int type)
463 8cbbe385 Blue Swirl
{
464 a8170e5e Avi Kivity
    hwaddr hash;
465 8cbbe385 Blue Swirl
    target_ulong vsid;
466 8cbbe385 Blue Swirl
    int ds, pr, target_page_bits;
467 0480884f David Gibson
    int ret;
468 0480884f David Gibson
    target_ulong sr, pgidx;
469 8cbbe385 Blue Swirl
470 8cbbe385 Blue Swirl
    pr = msr_pr;
471 8cbbe385 Blue Swirl
    ctx->eaddr = eaddr;
472 8cbbe385 Blue Swirl
473 0480884f David Gibson
    sr = env->sr[eaddr >> 28];
474 0480884f David Gibson
    ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
475 0480884f David Gibson
                ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
476 0480884f David Gibson
    ds = sr & 0x80000000 ? 1 : 0;
477 0480884f David Gibson
    ctx->nx = sr & 0x10000000 ? 1 : 0;
478 0480884f David Gibson
    vsid = sr & 0x00FFFFFF;
479 0480884f David Gibson
    target_page_bits = TARGET_PAGE_BITS;
480 0480884f David Gibson
    LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
481 0480884f David Gibson
            TARGET_FMT_lx " lr=" TARGET_FMT_lx
482 0480884f David Gibson
            " ir=%d dr=%d pr=%d %d t=%d\n",
483 0480884f David Gibson
            eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
484 0480884f David Gibson
            (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
485 0480884f David Gibson
    pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
486 0480884f David Gibson
    hash = vsid ^ pgidx;
487 0480884f David Gibson
    ctx->ptem = (vsid << 7) | (pgidx >> 10);
488 8cbbe385 Blue Swirl
489 8cbbe385 Blue Swirl
    LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
490 8cbbe385 Blue Swirl
            ctx->key, ds, ctx->nx, vsid);
491 8cbbe385 Blue Swirl
    ret = -1;
492 8cbbe385 Blue Swirl
    if (!ds) {
493 8cbbe385 Blue Swirl
        /* Check if instruction fetch is allowed, if needed */
494 8cbbe385 Blue Swirl
        if (type != ACCESS_CODE || ctx->nx == 0) {
495 8cbbe385 Blue Swirl
            /* Page address translation */
496 8cbbe385 Blue Swirl
            LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
497 8cbbe385 Blue Swirl
                    " hash " TARGET_FMT_plx "\n",
498 8cbbe385 Blue Swirl
                    env->htab_base, env->htab_mask, hash);
499 8cbbe385 Blue Swirl
            ctx->hash[0] = hash;
500 8cbbe385 Blue Swirl
            ctx->hash[1] = ~hash;
501 8cbbe385 Blue Swirl
502 8cbbe385 Blue Swirl
            /* Initialize real address with an invalid value */
503 a8170e5e Avi Kivity
            ctx->raddr = (hwaddr)-1ULL;
504 0480884f David Gibson
            /* Software TLB search */
505 0480884f David Gibson
            ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
506 8cbbe385 Blue Swirl
#if defined(DUMP_PAGE_TABLES)
507 8cbbe385 Blue Swirl
            if (qemu_log_enabled()) {
508 a8170e5e Avi Kivity
                hwaddr curaddr;
509 8cbbe385 Blue Swirl
                uint32_t a0, a1, a2, a3;
510 8cbbe385 Blue Swirl
511 8cbbe385 Blue Swirl
                qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
512 8cbbe385 Blue Swirl
                         "\n", sdr, mask + 0x80);
513 8cbbe385 Blue Swirl
                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
514 8cbbe385 Blue Swirl
                     curaddr += 16) {
515 8cbbe385 Blue Swirl
                    a0 = ldl_phys(curaddr);
516 8cbbe385 Blue Swirl
                    a1 = ldl_phys(curaddr + 4);
517 8cbbe385 Blue Swirl
                    a2 = ldl_phys(curaddr + 8);
518 8cbbe385 Blue Swirl
                    a3 = ldl_phys(curaddr + 12);
519 8cbbe385 Blue Swirl
                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
520 8cbbe385 Blue Swirl
                        qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
521 8cbbe385 Blue Swirl
                                 curaddr, a0, a1, a2, a3);
522 8cbbe385 Blue Swirl
                    }
523 8cbbe385 Blue Swirl
                }
524 8cbbe385 Blue Swirl
            }
525 8cbbe385 Blue Swirl
#endif
526 8cbbe385 Blue Swirl
        } else {
527 8cbbe385 Blue Swirl
            LOG_MMU("No access allowed\n");
528 8cbbe385 Blue Swirl
            ret = -3;
529 8cbbe385 Blue Swirl
        }
530 8cbbe385 Blue Swirl
    } else {
531 8cbbe385 Blue Swirl
        target_ulong sr;
532 8cbbe385 Blue Swirl
533 8cbbe385 Blue Swirl
        LOG_MMU("direct store...\n");
534 8cbbe385 Blue Swirl
        /* Direct-store segment : absolutely *BUGGY* for now */
535 8cbbe385 Blue Swirl
536 8cbbe385 Blue Swirl
        /* Direct-store implies a 32-bit MMU.
537 8cbbe385 Blue Swirl
         * Check the Segment Register's bus unit ID (BUID).
538 8cbbe385 Blue Swirl
         */
539 8cbbe385 Blue Swirl
        sr = env->sr[eaddr >> 28];
540 8cbbe385 Blue Swirl
        if ((sr & 0x1FF00000) >> 20 == 0x07f) {
541 8cbbe385 Blue Swirl
            /* Memory-forced I/O controller interface access */
542 8cbbe385 Blue Swirl
            /* If T=1 and BUID=x'07F', the 601 performs a memory access
543 8cbbe385 Blue Swirl
             * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
544 8cbbe385 Blue Swirl
             */
545 8cbbe385 Blue Swirl
            ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
546 8cbbe385 Blue Swirl
            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
547 8cbbe385 Blue Swirl
            return 0;
548 8cbbe385 Blue Swirl
        }
549 8cbbe385 Blue Swirl
550 8cbbe385 Blue Swirl
        switch (type) {
551 8cbbe385 Blue Swirl
        case ACCESS_INT:
552 8cbbe385 Blue Swirl
            /* Integer load/store : only access allowed */
553 8cbbe385 Blue Swirl
            break;
554 8cbbe385 Blue Swirl
        case ACCESS_CODE:
555 8cbbe385 Blue Swirl
            /* No code fetch is allowed in direct-store areas */
556 8cbbe385 Blue Swirl
            return -4;
557 8cbbe385 Blue Swirl
        case ACCESS_FLOAT:
558 8cbbe385 Blue Swirl
            /* Floating point load/store */
559 8cbbe385 Blue Swirl
            return -4;
560 8cbbe385 Blue Swirl
        case ACCESS_RES:
561 8cbbe385 Blue Swirl
            /* lwarx, ldarx or srwcx. */
562 8cbbe385 Blue Swirl
            return -4;
563 8cbbe385 Blue Swirl
        case ACCESS_CACHE:
564 8cbbe385 Blue Swirl
            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
565 8cbbe385 Blue Swirl
            /* Should make the instruction do no-op.
566 8cbbe385 Blue Swirl
             * As it already do no-op, it's quite easy :-)
567 8cbbe385 Blue Swirl
             */
568 8cbbe385 Blue Swirl
            ctx->raddr = eaddr;
569 8cbbe385 Blue Swirl
            return 0;
570 8cbbe385 Blue Swirl
        case ACCESS_EXT:
571 8cbbe385 Blue Swirl
            /* eciwx or ecowx */
572 8cbbe385 Blue Swirl
            return -4;
573 8cbbe385 Blue Swirl
        default:
574 8cbbe385 Blue Swirl
            qemu_log("ERROR: instruction should not need "
575 8cbbe385 Blue Swirl
                        "address translation\n");
576 8cbbe385 Blue Swirl
            return -4;
577 8cbbe385 Blue Swirl
        }
578 8cbbe385 Blue Swirl
        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
579 8cbbe385 Blue Swirl
            ctx->raddr = eaddr;
580 8cbbe385 Blue Swirl
            ret = 2;
581 8cbbe385 Blue Swirl
        } else {
582 8cbbe385 Blue Swirl
            ret = -2;
583 8cbbe385 Blue Swirl
        }
584 8cbbe385 Blue Swirl
    }
585 8cbbe385 Blue Swirl
586 8cbbe385 Blue Swirl
    return ret;
587 8cbbe385 Blue Swirl
}
588 8cbbe385 Blue Swirl
589 8cbbe385 Blue Swirl
/* Generic TLB check function for embedded PowerPC implementations */
590 9aa5b158 Blue Swirl
static int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
591 a8170e5e Avi Kivity
                            hwaddr *raddrp,
592 9aa5b158 Blue Swirl
                            target_ulong address, uint32_t pid, int ext,
593 9aa5b158 Blue Swirl
                            int i)
594 8cbbe385 Blue Swirl
{
595 8cbbe385 Blue Swirl
    target_ulong mask;
596 8cbbe385 Blue Swirl
597 8cbbe385 Blue Swirl
    /* Check valid flag */
598 8cbbe385 Blue Swirl
    if (!(tlb->prot & PAGE_VALID)) {
599 8cbbe385 Blue Swirl
        return -1;
600 8cbbe385 Blue Swirl
    }
601 8cbbe385 Blue Swirl
    mask = ~(tlb->size - 1);
602 8cbbe385 Blue Swirl
    LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
603 8cbbe385 Blue Swirl
              " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
604 8cbbe385 Blue Swirl
              mask, (uint32_t)tlb->PID, tlb->prot);
605 8cbbe385 Blue Swirl
    /* Check PID */
606 8cbbe385 Blue Swirl
    if (tlb->PID != 0 && tlb->PID != pid) {
607 8cbbe385 Blue Swirl
        return -1;
608 8cbbe385 Blue Swirl
    }
609 8cbbe385 Blue Swirl
    /* Check effective address */
610 8cbbe385 Blue Swirl
    if ((address & mask) != tlb->EPN) {
611 8cbbe385 Blue Swirl
        return -1;
612 8cbbe385 Blue Swirl
    }
613 8cbbe385 Blue Swirl
    *raddrp = (tlb->RPN & mask) | (address & ~mask);
614 8cbbe385 Blue Swirl
    if (ext) {
615 8cbbe385 Blue Swirl
        /* Extend the physical address to 36 bits */
616 4be403c8 Avi Kivity
        *raddrp |= (uint64_t)(tlb->RPN & 0xF) << 32;
617 8cbbe385 Blue Swirl
    }
618 8cbbe385 Blue Swirl
619 8cbbe385 Blue Swirl
    return 0;
620 8cbbe385 Blue Swirl
}
621 8cbbe385 Blue Swirl
622 8cbbe385 Blue Swirl
/* Generic TLB search function for PowerPC embedded implementations */
623 9aa5b158 Blue Swirl
static int ppcemb_tlb_search(CPUPPCState *env, target_ulong address,
624 9aa5b158 Blue Swirl
                             uint32_t pid)
625 8cbbe385 Blue Swirl
{
626 8cbbe385 Blue Swirl
    ppcemb_tlb_t *tlb;
627 a8170e5e Avi Kivity
    hwaddr raddr;
628 8cbbe385 Blue Swirl
    int i, ret;
629 8cbbe385 Blue Swirl
630 8cbbe385 Blue Swirl
    /* Default return value is no match */
631 8cbbe385 Blue Swirl
    ret = -1;
632 8cbbe385 Blue Swirl
    for (i = 0; i < env->nb_tlb; i++) {
633 8cbbe385 Blue Swirl
        tlb = &env->tlb.tlbe[i];
634 8cbbe385 Blue Swirl
        if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
635 8cbbe385 Blue Swirl
            ret = i;
636 8cbbe385 Blue Swirl
            break;
637 8cbbe385 Blue Swirl
        }
638 8cbbe385 Blue Swirl
    }
639 8cbbe385 Blue Swirl
640 8cbbe385 Blue Swirl
    return ret;
641 8cbbe385 Blue Swirl
}
642 8cbbe385 Blue Swirl
643 8cbbe385 Blue Swirl
/* Helpers specific to PowerPC 40x implementations */
644 8cbbe385 Blue Swirl
static inline void ppc4xx_tlb_invalidate_all(CPUPPCState *env)
645 8cbbe385 Blue Swirl
{
646 8cbbe385 Blue Swirl
    ppcemb_tlb_t *tlb;
647 8cbbe385 Blue Swirl
    int i;
648 8cbbe385 Blue Swirl
649 8cbbe385 Blue Swirl
    for (i = 0; i < env->nb_tlb; i++) {
650 8cbbe385 Blue Swirl
        tlb = &env->tlb.tlbe[i];
651 8cbbe385 Blue Swirl
        tlb->prot &= ~PAGE_VALID;
652 8cbbe385 Blue Swirl
    }
653 8cbbe385 Blue Swirl
    tlb_flush(env, 1);
654 8cbbe385 Blue Swirl
}
655 8cbbe385 Blue Swirl
656 8cbbe385 Blue Swirl
static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState *env,
657 8cbbe385 Blue Swirl
                                              target_ulong eaddr, uint32_t pid)
658 8cbbe385 Blue Swirl
{
659 8cbbe385 Blue Swirl
#if !defined(FLUSH_ALL_TLBS)
660 8cbbe385 Blue Swirl
    ppcemb_tlb_t *tlb;
661 a8170e5e Avi Kivity
    hwaddr raddr;
662 8cbbe385 Blue Swirl
    target_ulong page, end;
663 8cbbe385 Blue Swirl
    int i;
664 8cbbe385 Blue Swirl
665 8cbbe385 Blue Swirl
    for (i = 0; i < env->nb_tlb; i++) {
666 8cbbe385 Blue Swirl
        tlb = &env->tlb.tlbe[i];
667 8cbbe385 Blue Swirl
        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
668 8cbbe385 Blue Swirl
            end = tlb->EPN + tlb->size;
669 8cbbe385 Blue Swirl
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
670 8cbbe385 Blue Swirl
                tlb_flush_page(env, page);
671 8cbbe385 Blue Swirl
            }
672 8cbbe385 Blue Swirl
            tlb->prot &= ~PAGE_VALID;
673 8cbbe385 Blue Swirl
            break;
674 8cbbe385 Blue Swirl
        }
675 8cbbe385 Blue Swirl
    }
676 8cbbe385 Blue Swirl
#else
677 8cbbe385 Blue Swirl
    ppc4xx_tlb_invalidate_all(env);
678 8cbbe385 Blue Swirl
#endif
679 8cbbe385 Blue Swirl
}
680 8cbbe385 Blue Swirl
681 8cbbe385 Blue Swirl
static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
682 8cbbe385 Blue Swirl
                                       target_ulong address, int rw,
683 8cbbe385 Blue Swirl
                                       int access_type)
684 8cbbe385 Blue Swirl
{
685 8cbbe385 Blue Swirl
    ppcemb_tlb_t *tlb;
686 a8170e5e Avi Kivity
    hwaddr raddr;
687 8cbbe385 Blue Swirl
    int i, ret, zsel, zpr, pr;
688 8cbbe385 Blue Swirl
689 8cbbe385 Blue Swirl
    ret = -1;
690 a8170e5e Avi Kivity
    raddr = (hwaddr)-1ULL;
691 8cbbe385 Blue Swirl
    pr = msr_pr;
692 8cbbe385 Blue Swirl
    for (i = 0; i < env->nb_tlb; i++) {
693 8cbbe385 Blue Swirl
        tlb = &env->tlb.tlbe[i];
694 8cbbe385 Blue Swirl
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
695 8cbbe385 Blue Swirl
                             env->spr[SPR_40x_PID], 0, i) < 0) {
696 8cbbe385 Blue Swirl
            continue;
697 8cbbe385 Blue Swirl
        }
698 8cbbe385 Blue Swirl
        zsel = (tlb->attr >> 4) & 0xF;
699 8cbbe385 Blue Swirl
        zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
700 8cbbe385 Blue Swirl
        LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
701 8cbbe385 Blue Swirl
                    __func__, i, zsel, zpr, rw, tlb->attr);
702 8cbbe385 Blue Swirl
        /* Check execute enable bit */
703 8cbbe385 Blue Swirl
        switch (zpr) {
704 8cbbe385 Blue Swirl
        case 0x2:
705 8cbbe385 Blue Swirl
            if (pr != 0) {
706 8cbbe385 Blue Swirl
                goto check_perms;
707 8cbbe385 Blue Swirl
            }
708 8cbbe385 Blue Swirl
            /* No break here */
709 8cbbe385 Blue Swirl
        case 0x3:
710 8cbbe385 Blue Swirl
            /* All accesses granted */
711 8cbbe385 Blue Swirl
            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
712 8cbbe385 Blue Swirl
            ret = 0;
713 8cbbe385 Blue Swirl
            break;
714 8cbbe385 Blue Swirl
        case 0x0:
715 8cbbe385 Blue Swirl
            if (pr != 0) {
716 8cbbe385 Blue Swirl
                /* Raise Zone protection fault.  */
717 8cbbe385 Blue Swirl
                env->spr[SPR_40x_ESR] = 1 << 22;
718 8cbbe385 Blue Swirl
                ctx->prot = 0;
719 8cbbe385 Blue Swirl
                ret = -2;
720 8cbbe385 Blue Swirl
                break;
721 8cbbe385 Blue Swirl
            }
722 8cbbe385 Blue Swirl
            /* No break here */
723 8cbbe385 Blue Swirl
        case 0x1:
724 8cbbe385 Blue Swirl
        check_perms:
725 8cbbe385 Blue Swirl
            /* Check from TLB entry */
726 8cbbe385 Blue Swirl
            ctx->prot = tlb->prot;
727 8cbbe385 Blue Swirl
            ret = check_prot(ctx->prot, rw, access_type);
728 8cbbe385 Blue Swirl
            if (ret == -2) {
729 8cbbe385 Blue Swirl
                env->spr[SPR_40x_ESR] = 0;
730 8cbbe385 Blue Swirl
            }
731 8cbbe385 Blue Swirl
            break;
732 8cbbe385 Blue Swirl
        }
733 8cbbe385 Blue Swirl
        if (ret >= 0) {
734 8cbbe385 Blue Swirl
            ctx->raddr = raddr;
735 8cbbe385 Blue Swirl
            LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
736 8cbbe385 Blue Swirl
                      " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
737 8cbbe385 Blue Swirl
                      ret);
738 8cbbe385 Blue Swirl
            return 0;
739 8cbbe385 Blue Swirl
        }
740 8cbbe385 Blue Swirl
    }
741 8cbbe385 Blue Swirl
    LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
742 8cbbe385 Blue Swirl
              " %d %d\n", __func__, address, raddr, ctx->prot, ret);
743 8cbbe385 Blue Swirl
744 8cbbe385 Blue Swirl
    return ret;
745 8cbbe385 Blue Swirl
}
746 8cbbe385 Blue Swirl
747 8cbbe385 Blue Swirl
void store_40x_sler(CPUPPCState *env, uint32_t val)
748 8cbbe385 Blue Swirl
{
749 8cbbe385 Blue Swirl
    /* XXX: TO BE FIXED */
750 8cbbe385 Blue Swirl
    if (val != 0x00000000) {
751 8cbbe385 Blue Swirl
        cpu_abort(env, "Little-endian regions are not supported by now\n");
752 8cbbe385 Blue Swirl
    }
753 8cbbe385 Blue Swirl
    env->spr[SPR_405_SLER] = val;
754 8cbbe385 Blue Swirl
}
755 8cbbe385 Blue Swirl
756 8cbbe385 Blue Swirl
static inline int mmubooke_check_tlb(CPUPPCState *env, ppcemb_tlb_t *tlb,
757 a8170e5e Avi Kivity
                                     hwaddr *raddr, int *prot,
758 8cbbe385 Blue Swirl
                                     target_ulong address, int rw,
759 8cbbe385 Blue Swirl
                                     int access_type, int i)
760 8cbbe385 Blue Swirl
{
761 8cbbe385 Blue Swirl
    int ret, prot2;
762 8cbbe385 Blue Swirl
763 8cbbe385 Blue Swirl
    if (ppcemb_tlb_check(env, tlb, raddr, address,
764 8cbbe385 Blue Swirl
                         env->spr[SPR_BOOKE_PID],
765 8cbbe385 Blue Swirl
                         !env->nb_pids, i) >= 0) {
766 8cbbe385 Blue Swirl
        goto found_tlb;
767 8cbbe385 Blue Swirl
    }
768 8cbbe385 Blue Swirl
769 8cbbe385 Blue Swirl
    if (env->spr[SPR_BOOKE_PID1] &&
770 8cbbe385 Blue Swirl
        ppcemb_tlb_check(env, tlb, raddr, address,
771 8cbbe385 Blue Swirl
                         env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
772 8cbbe385 Blue Swirl
        goto found_tlb;
773 8cbbe385 Blue Swirl
    }
774 8cbbe385 Blue Swirl
775 8cbbe385 Blue Swirl
    if (env->spr[SPR_BOOKE_PID2] &&
776 8cbbe385 Blue Swirl
        ppcemb_tlb_check(env, tlb, raddr, address,
777 8cbbe385 Blue Swirl
                         env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
778 8cbbe385 Blue Swirl
        goto found_tlb;
779 8cbbe385 Blue Swirl
    }
780 8cbbe385 Blue Swirl
781 8cbbe385 Blue Swirl
    LOG_SWTLB("%s: TLB entry not found\n", __func__);
782 8cbbe385 Blue Swirl
    return -1;
783 8cbbe385 Blue Swirl
784 8cbbe385 Blue Swirl
found_tlb:
785 8cbbe385 Blue Swirl
786 8cbbe385 Blue Swirl
    if (msr_pr != 0) {
787 8cbbe385 Blue Swirl
        prot2 = tlb->prot & 0xF;
788 8cbbe385 Blue Swirl
    } else {
789 8cbbe385 Blue Swirl
        prot2 = (tlb->prot >> 4) & 0xF;
790 8cbbe385 Blue Swirl
    }
791 8cbbe385 Blue Swirl
792 8cbbe385 Blue Swirl
    /* Check the address space */
793 8cbbe385 Blue Swirl
    if (access_type == ACCESS_CODE) {
794 8cbbe385 Blue Swirl
        if (msr_ir != (tlb->attr & 1)) {
795 8cbbe385 Blue Swirl
            LOG_SWTLB("%s: AS doesn't match\n", __func__);
796 8cbbe385 Blue Swirl
            return -1;
797 8cbbe385 Blue Swirl
        }
798 8cbbe385 Blue Swirl
799 8cbbe385 Blue Swirl
        *prot = prot2;
800 8cbbe385 Blue Swirl
        if (prot2 & PAGE_EXEC) {
801 8cbbe385 Blue Swirl
            LOG_SWTLB("%s: good TLB!\n", __func__);
802 8cbbe385 Blue Swirl
            return 0;
803 8cbbe385 Blue Swirl
        }
804 8cbbe385 Blue Swirl
805 8cbbe385 Blue Swirl
        LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, prot2);
806 8cbbe385 Blue Swirl
        ret = -3;
807 8cbbe385 Blue Swirl
    } else {
808 8cbbe385 Blue Swirl
        if (msr_dr != (tlb->attr & 1)) {
809 8cbbe385 Blue Swirl
            LOG_SWTLB("%s: AS doesn't match\n", __func__);
810 8cbbe385 Blue Swirl
            return -1;
811 8cbbe385 Blue Swirl
        }
812 8cbbe385 Blue Swirl
813 8cbbe385 Blue Swirl
        *prot = prot2;
814 8cbbe385 Blue Swirl
        if ((!rw && prot2 & PAGE_READ) || (rw && (prot2 & PAGE_WRITE))) {
815 8cbbe385 Blue Swirl
            LOG_SWTLB("%s: found TLB!\n", __func__);
816 8cbbe385 Blue Swirl
            return 0;
817 8cbbe385 Blue Swirl
        }
818 8cbbe385 Blue Swirl
819 8cbbe385 Blue Swirl
        LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, prot2);
820 8cbbe385 Blue Swirl
        ret = -2;
821 8cbbe385 Blue Swirl
    }
822 8cbbe385 Blue Swirl
823 8cbbe385 Blue Swirl
    return ret;
824 8cbbe385 Blue Swirl
}
825 8cbbe385 Blue Swirl
826 8cbbe385 Blue Swirl
static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
827 8cbbe385 Blue Swirl
                                         target_ulong address, int rw,
828 8cbbe385 Blue Swirl
                                         int access_type)
829 8cbbe385 Blue Swirl
{
830 8cbbe385 Blue Swirl
    ppcemb_tlb_t *tlb;
831 a8170e5e Avi Kivity
    hwaddr raddr;
832 8cbbe385 Blue Swirl
    int i, ret;
833 8cbbe385 Blue Swirl
834 8cbbe385 Blue Swirl
    ret = -1;
835 a8170e5e Avi Kivity
    raddr = (hwaddr)-1ULL;
836 8cbbe385 Blue Swirl
    for (i = 0; i < env->nb_tlb; i++) {
837 8cbbe385 Blue Swirl
        tlb = &env->tlb.tlbe[i];
838 8cbbe385 Blue Swirl
        ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
839 8cbbe385 Blue Swirl
                                 access_type, i);
840 8cbbe385 Blue Swirl
        if (!ret) {
841 8cbbe385 Blue Swirl
            break;
842 8cbbe385 Blue Swirl
        }
843 8cbbe385 Blue Swirl
    }
844 8cbbe385 Blue Swirl
845 8cbbe385 Blue Swirl
    if (ret >= 0) {
846 8cbbe385 Blue Swirl
        ctx->raddr = raddr;
847 8cbbe385 Blue Swirl
        LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
848 8cbbe385 Blue Swirl
                  " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
849 8cbbe385 Blue Swirl
                  ret);
850 8cbbe385 Blue Swirl
    } else {
851 8cbbe385 Blue Swirl
        LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
852 8cbbe385 Blue Swirl
                  " %d %d\n", __func__, address, raddr, ctx->prot, ret);
853 8cbbe385 Blue Swirl
    }
854 8cbbe385 Blue Swirl
855 8cbbe385 Blue Swirl
    return ret;
856 8cbbe385 Blue Swirl
}
857 8cbbe385 Blue Swirl
858 6575c289 Blue Swirl
static void booke206_flush_tlb(CPUPPCState *env, int flags,
859 6575c289 Blue Swirl
                               const int check_iprot)
860 8cbbe385 Blue Swirl
{
861 8cbbe385 Blue Swirl
    int tlb_size;
862 8cbbe385 Blue Swirl
    int i, j;
863 8cbbe385 Blue Swirl
    ppcmas_tlb_t *tlb = env->tlb.tlbm;
864 8cbbe385 Blue Swirl
865 8cbbe385 Blue Swirl
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
866 8cbbe385 Blue Swirl
        if (flags & (1 << i)) {
867 8cbbe385 Blue Swirl
            tlb_size = booke206_tlb_size(env, i);
868 8cbbe385 Blue Swirl
            for (j = 0; j < tlb_size; j++) {
869 8cbbe385 Blue Swirl
                if (!check_iprot || !(tlb[j].mas1 & MAS1_IPROT)) {
870 8cbbe385 Blue Swirl
                    tlb[j].mas1 &= ~MAS1_VALID;
871 8cbbe385 Blue Swirl
                }
872 8cbbe385 Blue Swirl
            }
873 8cbbe385 Blue Swirl
        }
874 8cbbe385 Blue Swirl
        tlb += booke206_tlb_size(env, i);
875 8cbbe385 Blue Swirl
    }
876 8cbbe385 Blue Swirl
877 8cbbe385 Blue Swirl
    tlb_flush(env, 1);
878 8cbbe385 Blue Swirl
}
879 8cbbe385 Blue Swirl
880 6575c289 Blue Swirl
static hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
881 6575c289 Blue Swirl
                                        ppcmas_tlb_t *tlb)
882 8cbbe385 Blue Swirl
{
883 8cbbe385 Blue Swirl
    int tlbm_size;
884 8cbbe385 Blue Swirl
885 8cbbe385 Blue Swirl
    tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
886 8cbbe385 Blue Swirl
887 8cbbe385 Blue Swirl
    return 1024ULL << tlbm_size;
888 8cbbe385 Blue Swirl
}
889 8cbbe385 Blue Swirl
890 8cbbe385 Blue Swirl
/* TLB check function for MAS based SoftTLBs */
891 213c7180 David Gibson
static int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
892 213c7180 David Gibson
                            hwaddr *raddrp,
893 10b46525 David Gibson
                     target_ulong address, uint32_t pid)
894 8cbbe385 Blue Swirl
{
895 8cbbe385 Blue Swirl
    target_ulong mask;
896 8cbbe385 Blue Swirl
    uint32_t tlb_pid;
897 8cbbe385 Blue Swirl
898 8cbbe385 Blue Swirl
    /* Check valid flag */
899 8cbbe385 Blue Swirl
    if (!(tlb->mas1 & MAS1_VALID)) {
900 8cbbe385 Blue Swirl
        return -1;
901 8cbbe385 Blue Swirl
    }
902 8cbbe385 Blue Swirl
903 8cbbe385 Blue Swirl
    mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
904 8cbbe385 Blue Swirl
    LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%"
905 8cbbe385 Blue Swirl
              PRIx64 " mask=0x" TARGET_FMT_lx " MAS7_3=0x%" PRIx64 " MAS8=%x\n",
906 8cbbe385 Blue Swirl
              __func__, address, pid, tlb->mas1, tlb->mas2, mask, tlb->mas7_3,
907 8cbbe385 Blue Swirl
              tlb->mas8);
908 8cbbe385 Blue Swirl
909 8cbbe385 Blue Swirl
    /* Check PID */
910 8cbbe385 Blue Swirl
    tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
911 8cbbe385 Blue Swirl
    if (tlb_pid != 0 && tlb_pid != pid) {
912 8cbbe385 Blue Swirl
        return -1;
913 8cbbe385 Blue Swirl
    }
914 8cbbe385 Blue Swirl
915 8cbbe385 Blue Swirl
    /* Check effective address */
916 8cbbe385 Blue Swirl
    if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
917 8cbbe385 Blue Swirl
        return -1;
918 8cbbe385 Blue Swirl
    }
919 8cbbe385 Blue Swirl
920 8cbbe385 Blue Swirl
    if (raddrp) {
921 8cbbe385 Blue Swirl
        *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
922 8cbbe385 Blue Swirl
    }
923 8cbbe385 Blue Swirl
924 8cbbe385 Blue Swirl
    return 0;
925 8cbbe385 Blue Swirl
}
926 8cbbe385 Blue Swirl
927 8cbbe385 Blue Swirl
static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb,
928 a8170e5e Avi Kivity
                                 hwaddr *raddr, int *prot,
929 8cbbe385 Blue Swirl
                                 target_ulong address, int rw,
930 8cbbe385 Blue Swirl
                                 int access_type)
931 8cbbe385 Blue Swirl
{
932 8cbbe385 Blue Swirl
    int ret;
933 8cbbe385 Blue Swirl
    int prot2 = 0;
934 8cbbe385 Blue Swirl
935 8cbbe385 Blue Swirl
    if (ppcmas_tlb_check(env, tlb, raddr, address,
936 8cbbe385 Blue Swirl
                         env->spr[SPR_BOOKE_PID]) >= 0) {
937 8cbbe385 Blue Swirl
        goto found_tlb;
938 8cbbe385 Blue Swirl
    }
939 8cbbe385 Blue Swirl
940 8cbbe385 Blue Swirl
    if (env->spr[SPR_BOOKE_PID1] &&
941 8cbbe385 Blue Swirl
        ppcmas_tlb_check(env, tlb, raddr, address,
942 8cbbe385 Blue Swirl
                         env->spr[SPR_BOOKE_PID1]) >= 0) {
943 8cbbe385 Blue Swirl
        goto found_tlb;
944 8cbbe385 Blue Swirl
    }
945 8cbbe385 Blue Swirl
946 8cbbe385 Blue Swirl
    if (env->spr[SPR_BOOKE_PID2] &&
947 8cbbe385 Blue Swirl
        ppcmas_tlb_check(env, tlb, raddr, address,
948 8cbbe385 Blue Swirl
                         env->spr[SPR_BOOKE_PID2]) >= 0) {
949 8cbbe385 Blue Swirl
        goto found_tlb;
950 8cbbe385 Blue Swirl
    }
951 8cbbe385 Blue Swirl
952 8cbbe385 Blue Swirl
    LOG_SWTLB("%s: TLB entry not found\n", __func__);
953 8cbbe385 Blue Swirl
    return -1;
954 8cbbe385 Blue Swirl
955 8cbbe385 Blue Swirl
found_tlb:
956 8cbbe385 Blue Swirl
957 8cbbe385 Blue Swirl
    if (msr_pr != 0) {
958 8cbbe385 Blue Swirl
        if (tlb->mas7_3 & MAS3_UR) {
959 8cbbe385 Blue Swirl
            prot2 |= PAGE_READ;
960 8cbbe385 Blue Swirl
        }
961 8cbbe385 Blue Swirl
        if (tlb->mas7_3 & MAS3_UW) {
962 8cbbe385 Blue Swirl
            prot2 |= PAGE_WRITE;
963 8cbbe385 Blue Swirl
        }
964 8cbbe385 Blue Swirl
        if (tlb->mas7_3 & MAS3_UX) {
965 8cbbe385 Blue Swirl
            prot2 |= PAGE_EXEC;
966 8cbbe385 Blue Swirl
        }
967 8cbbe385 Blue Swirl
    } else {
968 8cbbe385 Blue Swirl
        if (tlb->mas7_3 & MAS3_SR) {
969 8cbbe385 Blue Swirl
            prot2 |= PAGE_READ;
970 8cbbe385 Blue Swirl
        }
971 8cbbe385 Blue Swirl
        if (tlb->mas7_3 & MAS3_SW) {
972 8cbbe385 Blue Swirl
            prot2 |= PAGE_WRITE;
973 8cbbe385 Blue Swirl
        }
974 8cbbe385 Blue Swirl
        if (tlb->mas7_3 & MAS3_SX) {
975 8cbbe385 Blue Swirl
            prot2 |= PAGE_EXEC;
976 8cbbe385 Blue Swirl
        }
977 8cbbe385 Blue Swirl
    }
978 8cbbe385 Blue Swirl
979 8cbbe385 Blue Swirl
    /* Check the address space and permissions */
980 8cbbe385 Blue Swirl
    if (access_type == ACCESS_CODE) {
981 8cbbe385 Blue Swirl
        if (msr_ir != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
982 8cbbe385 Blue Swirl
            LOG_SWTLB("%s: AS doesn't match\n", __func__);
983 8cbbe385 Blue Swirl
            return -1;
984 8cbbe385 Blue Swirl
        }
985 8cbbe385 Blue Swirl
986 8cbbe385 Blue Swirl
        *prot = prot2;
987 8cbbe385 Blue Swirl
        if (prot2 & PAGE_EXEC) {
988 8cbbe385 Blue Swirl
            LOG_SWTLB("%s: good TLB!\n", __func__);
989 8cbbe385 Blue Swirl
            return 0;
990 8cbbe385 Blue Swirl
        }
991 8cbbe385 Blue Swirl
992 8cbbe385 Blue Swirl
        LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, prot2);
993 8cbbe385 Blue Swirl
        ret = -3;
994 8cbbe385 Blue Swirl
    } else {
995 8cbbe385 Blue Swirl
        if (msr_dr != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
996 8cbbe385 Blue Swirl
            LOG_SWTLB("%s: AS doesn't match\n", __func__);
997 8cbbe385 Blue Swirl
            return -1;
998 8cbbe385 Blue Swirl
        }
999 8cbbe385 Blue Swirl
1000 8cbbe385 Blue Swirl
        *prot = prot2;
1001 8cbbe385 Blue Swirl
        if ((!rw && prot2 & PAGE_READ) || (rw && (prot2 & PAGE_WRITE))) {
1002 8cbbe385 Blue Swirl
            LOG_SWTLB("%s: found TLB!\n", __func__);
1003 8cbbe385 Blue Swirl
            return 0;
1004 8cbbe385 Blue Swirl
        }
1005 8cbbe385 Blue Swirl
1006 8cbbe385 Blue Swirl
        LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, prot2);
1007 8cbbe385 Blue Swirl
        ret = -2;
1008 8cbbe385 Blue Swirl
    }
1009 8cbbe385 Blue Swirl
1010 8cbbe385 Blue Swirl
    return ret;
1011 8cbbe385 Blue Swirl
}
1012 8cbbe385 Blue Swirl
1013 8cbbe385 Blue Swirl
static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
1014 8cbbe385 Blue Swirl
                                            target_ulong address, int rw,
1015 8cbbe385 Blue Swirl
                                            int access_type)
1016 8cbbe385 Blue Swirl
{
1017 8cbbe385 Blue Swirl
    ppcmas_tlb_t *tlb;
1018 a8170e5e Avi Kivity
    hwaddr raddr;
1019 8cbbe385 Blue Swirl
    int i, j, ret;
1020 8cbbe385 Blue Swirl
1021 8cbbe385 Blue Swirl
    ret = -1;
1022 a8170e5e Avi Kivity
    raddr = (hwaddr)-1ULL;
1023 8cbbe385 Blue Swirl
1024 8cbbe385 Blue Swirl
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1025 8cbbe385 Blue Swirl
        int ways = booke206_tlb_ways(env, i);
1026 8cbbe385 Blue Swirl
1027 8cbbe385 Blue Swirl
        for (j = 0; j < ways; j++) {
1028 8cbbe385 Blue Swirl
            tlb = booke206_get_tlbm(env, i, address, j);
1029 8cbbe385 Blue Swirl
            if (!tlb) {
1030 8cbbe385 Blue Swirl
                continue;
1031 8cbbe385 Blue Swirl
            }
1032 8cbbe385 Blue Swirl
            ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
1033 8cbbe385 Blue Swirl
                                        rw, access_type);
1034 8cbbe385 Blue Swirl
            if (ret != -1) {
1035 8cbbe385 Blue Swirl
                goto found_tlb;
1036 8cbbe385 Blue Swirl
            }
1037 8cbbe385 Blue Swirl
        }
1038 8cbbe385 Blue Swirl
    }
1039 8cbbe385 Blue Swirl
1040 8cbbe385 Blue Swirl
found_tlb:
1041 8cbbe385 Blue Swirl
1042 8cbbe385 Blue Swirl
    if (ret >= 0) {
1043 8cbbe385 Blue Swirl
        ctx->raddr = raddr;
1044 8cbbe385 Blue Swirl
        LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1045 8cbbe385 Blue Swirl
                  " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1046 8cbbe385 Blue Swirl
                  ret);
1047 8cbbe385 Blue Swirl
    } else {
1048 8cbbe385 Blue Swirl
        LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1049 8cbbe385 Blue Swirl
                  " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1050 8cbbe385 Blue Swirl
    }
1051 8cbbe385 Blue Swirl
1052 8cbbe385 Blue Swirl
    return ret;
1053 8cbbe385 Blue Swirl
}
1054 8cbbe385 Blue Swirl
1055 8cbbe385 Blue Swirl
static const char *book3e_tsize_to_str[32] = {
1056 8cbbe385 Blue Swirl
    "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1057 8cbbe385 Blue Swirl
    "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1058 8cbbe385 Blue Swirl
    "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1059 8cbbe385 Blue Swirl
    "1T", "2T"
1060 8cbbe385 Blue Swirl
};
1061 8cbbe385 Blue Swirl
1062 8cbbe385 Blue Swirl
static void mmubooke_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
1063 8cbbe385 Blue Swirl
                                 CPUPPCState *env)
1064 8cbbe385 Blue Swirl
{
1065 8cbbe385 Blue Swirl
    ppcemb_tlb_t *entry;
1066 8cbbe385 Blue Swirl
    int i;
1067 8cbbe385 Blue Swirl
1068 8cbbe385 Blue Swirl
    if (kvm_enabled() && !env->kvm_sw_tlb) {
1069 8cbbe385 Blue Swirl
        cpu_fprintf(f, "Cannot access KVM TLB\n");
1070 8cbbe385 Blue Swirl
        return;
1071 8cbbe385 Blue Swirl
    }
1072 8cbbe385 Blue Swirl
1073 8cbbe385 Blue Swirl
    cpu_fprintf(f, "\nTLB:\n");
1074 8cbbe385 Blue Swirl
    cpu_fprintf(f, "Effective          Physical           Size PID   Prot     "
1075 8cbbe385 Blue Swirl
                "Attr\n");
1076 8cbbe385 Blue Swirl
1077 8cbbe385 Blue Swirl
    entry = &env->tlb.tlbe[0];
1078 8cbbe385 Blue Swirl
    for (i = 0; i < env->nb_tlb; i++, entry++) {
1079 a8170e5e Avi Kivity
        hwaddr ea, pa;
1080 8cbbe385 Blue Swirl
        target_ulong mask;
1081 8cbbe385 Blue Swirl
        uint64_t size = (uint64_t)entry->size;
1082 8cbbe385 Blue Swirl
        char size_buf[20];
1083 8cbbe385 Blue Swirl
1084 8cbbe385 Blue Swirl
        /* Check valid flag */
1085 8cbbe385 Blue Swirl
        if (!(entry->prot & PAGE_VALID)) {
1086 8cbbe385 Blue Swirl
            continue;
1087 8cbbe385 Blue Swirl
        }
1088 8cbbe385 Blue Swirl
1089 8cbbe385 Blue Swirl
        mask = ~(entry->size - 1);
1090 8cbbe385 Blue Swirl
        ea = entry->EPN & mask;
1091 8cbbe385 Blue Swirl
        pa = entry->RPN & mask;
1092 8cbbe385 Blue Swirl
        /* Extend the physical address to 36 bits */
1093 a8170e5e Avi Kivity
        pa |= (hwaddr)(entry->RPN & 0xF) << 32;
1094 8cbbe385 Blue Swirl
        size /= 1024;
1095 8cbbe385 Blue Swirl
        if (size >= 1024) {
1096 8cbbe385 Blue Swirl
            snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / 1024);
1097 8cbbe385 Blue Swirl
        } else {
1098 8cbbe385 Blue Swirl
            snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size);
1099 8cbbe385 Blue Swirl
        }
1100 8cbbe385 Blue Swirl
        cpu_fprintf(f, "0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n",
1101 8cbbe385 Blue Swirl
                    (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID,
1102 8cbbe385 Blue Swirl
                    entry->prot, entry->attr);
1103 8cbbe385 Blue Swirl
    }
1104 8cbbe385 Blue Swirl
1105 8cbbe385 Blue Swirl
}
1106 8cbbe385 Blue Swirl
1107 8cbbe385 Blue Swirl
static void mmubooke206_dump_one_tlb(FILE *f, fprintf_function cpu_fprintf,
1108 8cbbe385 Blue Swirl
                                     CPUPPCState *env, int tlbn, int offset,
1109 8cbbe385 Blue Swirl
                                     int tlbsize)
1110 8cbbe385 Blue Swirl
{
1111 8cbbe385 Blue Swirl
    ppcmas_tlb_t *entry;
1112 8cbbe385 Blue Swirl
    int i;
1113 8cbbe385 Blue Swirl
1114 8cbbe385 Blue Swirl
    cpu_fprintf(f, "\nTLB%d:\n", tlbn);
1115 8cbbe385 Blue Swirl
    cpu_fprintf(f, "Effective          Physical           Size TID   TS SRWX"
1116 8cbbe385 Blue Swirl
                " URWX WIMGE U0123\n");
1117 8cbbe385 Blue Swirl
1118 8cbbe385 Blue Swirl
    entry = &env->tlb.tlbm[offset];
1119 8cbbe385 Blue Swirl
    for (i = 0; i < tlbsize; i++, entry++) {
1120 a8170e5e Avi Kivity
        hwaddr ea, pa, size;
1121 8cbbe385 Blue Swirl
        int tsize;
1122 8cbbe385 Blue Swirl
1123 8cbbe385 Blue Swirl
        if (!(entry->mas1 & MAS1_VALID)) {
1124 8cbbe385 Blue Swirl
            continue;
1125 8cbbe385 Blue Swirl
        }
1126 8cbbe385 Blue Swirl
1127 8cbbe385 Blue Swirl
        tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1128 8cbbe385 Blue Swirl
        size = 1024ULL << tsize;
1129 8cbbe385 Blue Swirl
        ea = entry->mas2 & ~(size - 1);
1130 8cbbe385 Blue Swirl
        pa = entry->mas7_3 & ~(size - 1);
1131 8cbbe385 Blue Swirl
1132 8cbbe385 Blue Swirl
        cpu_fprintf(f, "0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u  S%c%c%c"
1133 8cbbe385 Blue Swirl
                    "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1134 8cbbe385 Blue Swirl
                    (uint64_t)ea, (uint64_t)pa,
1135 8cbbe385 Blue Swirl
                    book3e_tsize_to_str[tsize],
1136 8cbbe385 Blue Swirl
                    (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
1137 8cbbe385 Blue Swirl
                    (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
1138 8cbbe385 Blue Swirl
                    entry->mas7_3 & MAS3_SR ? 'R' : '-',
1139 8cbbe385 Blue Swirl
                    entry->mas7_3 & MAS3_SW ? 'W' : '-',
1140 8cbbe385 Blue Swirl
                    entry->mas7_3 & MAS3_SX ? 'X' : '-',
1141 8cbbe385 Blue Swirl
                    entry->mas7_3 & MAS3_UR ? 'R' : '-',
1142 8cbbe385 Blue Swirl
                    entry->mas7_3 & MAS3_UW ? 'W' : '-',
1143 8cbbe385 Blue Swirl
                    entry->mas7_3 & MAS3_UX ? 'X' : '-',
1144 8cbbe385 Blue Swirl
                    entry->mas2 & MAS2_W ? 'W' : '-',
1145 8cbbe385 Blue Swirl
                    entry->mas2 & MAS2_I ? 'I' : '-',
1146 8cbbe385 Blue Swirl
                    entry->mas2 & MAS2_M ? 'M' : '-',
1147 8cbbe385 Blue Swirl
                    entry->mas2 & MAS2_G ? 'G' : '-',
1148 8cbbe385 Blue Swirl
                    entry->mas2 & MAS2_E ? 'E' : '-',
1149 8cbbe385 Blue Swirl
                    entry->mas7_3 & MAS3_U0 ? '0' : '-',
1150 8cbbe385 Blue Swirl
                    entry->mas7_3 & MAS3_U1 ? '1' : '-',
1151 8cbbe385 Blue Swirl
                    entry->mas7_3 & MAS3_U2 ? '2' : '-',
1152 8cbbe385 Blue Swirl
                    entry->mas7_3 & MAS3_U3 ? '3' : '-');
1153 8cbbe385 Blue Swirl
    }
1154 8cbbe385 Blue Swirl
}
1155 8cbbe385 Blue Swirl
1156 8cbbe385 Blue Swirl
static void mmubooke206_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
1157 8cbbe385 Blue Swirl
                                 CPUPPCState *env)
1158 8cbbe385 Blue Swirl
{
1159 8cbbe385 Blue Swirl
    int offset = 0;
1160 8cbbe385 Blue Swirl
    int i;
1161 8cbbe385 Blue Swirl
1162 8cbbe385 Blue Swirl
    if (kvm_enabled() && !env->kvm_sw_tlb) {
1163 8cbbe385 Blue Swirl
        cpu_fprintf(f, "Cannot access KVM TLB\n");
1164 8cbbe385 Blue Swirl
        return;
1165 8cbbe385 Blue Swirl
    }
1166 8cbbe385 Blue Swirl
1167 8cbbe385 Blue Swirl
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1168 8cbbe385 Blue Swirl
        int size = booke206_tlb_size(env, i);
1169 8cbbe385 Blue Swirl
1170 8cbbe385 Blue Swirl
        if (size == 0) {
1171 8cbbe385 Blue Swirl
            continue;
1172 8cbbe385 Blue Swirl
        }
1173 8cbbe385 Blue Swirl
1174 8cbbe385 Blue Swirl
        mmubooke206_dump_one_tlb(f, cpu_fprintf, env, i, offset, size);
1175 8cbbe385 Blue Swirl
        offset += size;
1176 8cbbe385 Blue Swirl
    }
1177 8cbbe385 Blue Swirl
}
1178 8cbbe385 Blue Swirl
1179 8cbbe385 Blue Swirl
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
1180 8cbbe385 Blue Swirl
{
1181 8cbbe385 Blue Swirl
    switch (env->mmu_model) {
1182 8cbbe385 Blue Swirl
    case POWERPC_MMU_BOOKE:
1183 8cbbe385 Blue Swirl
        mmubooke_dump_mmu(f, cpu_fprintf, env);
1184 8cbbe385 Blue Swirl
        break;
1185 8cbbe385 Blue Swirl
    case POWERPC_MMU_BOOKE206:
1186 8cbbe385 Blue Swirl
        mmubooke206_dump_mmu(f, cpu_fprintf, env);
1187 8cbbe385 Blue Swirl
        break;
1188 8cbbe385 Blue Swirl
#if defined(TARGET_PPC64)
1189 8cbbe385 Blue Swirl
    case POWERPC_MMU_64B:
1190 8cbbe385 Blue Swirl
    case POWERPC_MMU_2_06:
1191 126a7930 Alexander Graf
    case POWERPC_MMU_2_06a:
1192 4656e1f0 Benjamin Herrenschmidt
    case POWERPC_MMU_2_06d:
1193 10b46525 David Gibson
        dump_slb(f, cpu_fprintf, env);
1194 8cbbe385 Blue Swirl
        break;
1195 8cbbe385 Blue Swirl
#endif
1196 8cbbe385 Blue Swirl
    default:
1197 8cbbe385 Blue Swirl
        qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
1198 8cbbe385 Blue Swirl
    }
1199 8cbbe385 Blue Swirl
}
1200 8cbbe385 Blue Swirl
1201 8cbbe385 Blue Swirl
static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
1202 8cbbe385 Blue Swirl
                                 target_ulong eaddr, int rw)
1203 8cbbe385 Blue Swirl
{
1204 8cbbe385 Blue Swirl
    int in_plb, ret;
1205 8cbbe385 Blue Swirl
1206 8cbbe385 Blue Swirl
    ctx->raddr = eaddr;
1207 8cbbe385 Blue Swirl
    ctx->prot = PAGE_READ | PAGE_EXEC;
1208 8cbbe385 Blue Swirl
    ret = 0;
1209 8cbbe385 Blue Swirl
    switch (env->mmu_model) {
1210 8cbbe385 Blue Swirl
    case POWERPC_MMU_SOFT_6xx:
1211 8cbbe385 Blue Swirl
    case POWERPC_MMU_SOFT_74xx:
1212 8cbbe385 Blue Swirl
    case POWERPC_MMU_SOFT_4xx:
1213 8cbbe385 Blue Swirl
    case POWERPC_MMU_REAL:
1214 8cbbe385 Blue Swirl
    case POWERPC_MMU_BOOKE:
1215 8cbbe385 Blue Swirl
        ctx->prot |= PAGE_WRITE;
1216 8cbbe385 Blue Swirl
        break;
1217 629bd516 David Gibson
1218 8cbbe385 Blue Swirl
    case POWERPC_MMU_SOFT_4xx_Z:
1219 8cbbe385 Blue Swirl
        if (unlikely(msr_pe != 0)) {
1220 8cbbe385 Blue Swirl
            /* 403 family add some particular protections,
1221 8cbbe385 Blue Swirl
             * using PBL/PBU registers for accesses with no translation.
1222 8cbbe385 Blue Swirl
             */
1223 8cbbe385 Blue Swirl
            in_plb =
1224 8cbbe385 Blue Swirl
                /* Check PLB validity */
1225 8cbbe385 Blue Swirl
                (env->pb[0] < env->pb[1] &&
1226 8cbbe385 Blue Swirl
                 /* and address in plb area */
1227 8cbbe385 Blue Swirl
                 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1228 8cbbe385 Blue Swirl
                (env->pb[2] < env->pb[3] &&
1229 8cbbe385 Blue Swirl
                 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1230 8cbbe385 Blue Swirl
            if (in_plb ^ msr_px) {
1231 8cbbe385 Blue Swirl
                /* Access in protected area */
1232 8cbbe385 Blue Swirl
                if (rw == 1) {
1233 8cbbe385 Blue Swirl
                    /* Access is not allowed */
1234 8cbbe385 Blue Swirl
                    ret = -2;
1235 8cbbe385 Blue Swirl
                }
1236 8cbbe385 Blue Swirl
            } else {
1237 8cbbe385 Blue Swirl
                /* Read-write access is allowed */
1238 8cbbe385 Blue Swirl
                ctx->prot |= PAGE_WRITE;
1239 8cbbe385 Blue Swirl
            }
1240 8cbbe385 Blue Swirl
        }
1241 8cbbe385 Blue Swirl
        break;
1242 629bd516 David Gibson
1243 8cbbe385 Blue Swirl
    default:
1244 629bd516 David Gibson
        /* Caller's checks mean we should never get here for other models */
1245 629bd516 David Gibson
        abort();
1246 8cbbe385 Blue Swirl
        return -1;
1247 8cbbe385 Blue Swirl
    }
1248 8cbbe385 Blue Swirl
1249 8cbbe385 Blue Swirl
    return ret;
1250 8cbbe385 Blue Swirl
}
1251 8cbbe385 Blue Swirl
1252 6575c289 Blue Swirl
static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
1253 6575c289 Blue Swirl
                                target_ulong eaddr, int rw, int access_type)
1254 8cbbe385 Blue Swirl
{
1255 44bc9107 David Gibson
    int ret = -1;
1256 44bc9107 David Gibson
    bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
1257 44bc9107 David Gibson
        || (access_type != ACCESS_CODE && msr_dr == 0);
1258 8cbbe385 Blue Swirl
1259 8cbbe385 Blue Swirl
#if 0
1260 8cbbe385 Blue Swirl
    qemu_log("%s\n", __func__);
1261 8cbbe385 Blue Swirl
#endif
1262 44bc9107 David Gibson
1263 44bc9107 David Gibson
    switch (env->mmu_model) {
1264 44bc9107 David Gibson
    case POWERPC_MMU_SOFT_6xx:
1265 44bc9107 David Gibson
    case POWERPC_MMU_SOFT_74xx:
1266 44bc9107 David Gibson
        if (real_mode) {
1267 44bc9107 David Gibson
            ret = check_physical(env, ctx, eaddr, rw);
1268 44bc9107 David Gibson
        } else {
1269 8cbbe385 Blue Swirl
            /* Try to find a BAT */
1270 8cbbe385 Blue Swirl
            if (env->nb_BATs != 0) {
1271 98132796 David Gibson
                ret = get_bat_6xx_tlb(env, ctx, eaddr, rw, access_type);
1272 8cbbe385 Blue Swirl
            }
1273 0480884f David Gibson
            if (ret < 0) {
1274 0480884f David Gibson
                /* We didn't match any BAT entry or don't have BATs */
1275 0480884f David Gibson
                ret = get_segment_6xx_tlb(env, ctx, eaddr, rw, access_type);
1276 0480884f David Gibson
            }
1277 44bc9107 David Gibson
        }
1278 44bc9107 David Gibson
        break;
1279 0480884f David Gibson
1280 44bc9107 David Gibson
    case POWERPC_MMU_SOFT_4xx:
1281 44bc9107 David Gibson
    case POWERPC_MMU_SOFT_4xx_Z:
1282 44bc9107 David Gibson
        if (real_mode) {
1283 44bc9107 David Gibson
            ret = check_physical(env, ctx, eaddr, rw);
1284 44bc9107 David Gibson
        } else {
1285 8cbbe385 Blue Swirl
            ret = mmu40x_get_physical_address(env, ctx, eaddr,
1286 8cbbe385 Blue Swirl
                                              rw, access_type);
1287 44bc9107 David Gibson
        }
1288 44bc9107 David Gibson
        break;
1289 44bc9107 David Gibson
    case POWERPC_MMU_BOOKE:
1290 44bc9107 David Gibson
        ret = mmubooke_get_physical_address(env, ctx, eaddr,
1291 44bc9107 David Gibson
                                            rw, access_type);
1292 44bc9107 David Gibson
        break;
1293 44bc9107 David Gibson
    case POWERPC_MMU_BOOKE206:
1294 44bc9107 David Gibson
        ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1295 8cbbe385 Blue Swirl
                                               access_type);
1296 44bc9107 David Gibson
        break;
1297 44bc9107 David Gibson
    case POWERPC_MMU_MPC8xx:
1298 44bc9107 David Gibson
        /* XXX: TODO */
1299 44bc9107 David Gibson
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1300 44bc9107 David Gibson
        break;
1301 44bc9107 David Gibson
    case POWERPC_MMU_REAL:
1302 44bc9107 David Gibson
        if (real_mode) {
1303 44bc9107 David Gibson
            ret = check_physical(env, ctx, eaddr, rw);
1304 44bc9107 David Gibson
        } else {
1305 8cbbe385 Blue Swirl
            cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1306 8cbbe385 Blue Swirl
        }
1307 44bc9107 David Gibson
        return -1;
1308 44bc9107 David Gibson
    default:
1309 44bc9107 David Gibson
        cpu_abort(env, "Unknown or invalid MMU model\n");
1310 44bc9107 David Gibson
        return -1;
1311 8cbbe385 Blue Swirl
    }
1312 8cbbe385 Blue Swirl
#if 0
1313 8cbbe385 Blue Swirl
    qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1314 8cbbe385 Blue Swirl
             __func__, eaddr, ret, ctx->raddr);
1315 8cbbe385 Blue Swirl
#endif
1316 8cbbe385 Blue Swirl
1317 8cbbe385 Blue Swirl
    return ret;
1318 8cbbe385 Blue Swirl
}
1319 8cbbe385 Blue Swirl
1320 a8170e5e Avi Kivity
hwaddr cpu_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
1321 8cbbe385 Blue Swirl
{
1322 8cbbe385 Blue Swirl
    mmu_ctx_t ctx;
1323 8cbbe385 Blue Swirl
1324 f2ad6be8 David Gibson
    switch (env->mmu_model) {
1325 f2ad6be8 David Gibson
#if defined(TARGET_PPC64)
1326 f2ad6be8 David Gibson
    case POWERPC_MMU_64B:
1327 f2ad6be8 David Gibson
    case POWERPC_MMU_2_06:
1328 126a7930 Alexander Graf
    case POWERPC_MMU_2_06a:
1329 f2ad6be8 David Gibson
    case POWERPC_MMU_2_06d:
1330 f2ad6be8 David Gibson
        return ppc_hash64_get_phys_page_debug(env, addr);
1331 f2ad6be8 David Gibson
#endif
1332 f2ad6be8 David Gibson
1333 f2ad6be8 David Gibson
    case POWERPC_MMU_32B:
1334 f2ad6be8 David Gibson
    case POWERPC_MMU_601:
1335 f2ad6be8 David Gibson
        return ppc_hash32_get_phys_page_debug(env, addr);
1336 f2ad6be8 David Gibson
1337 f2ad6be8 David Gibson
    default:
1338 f2ad6be8 David Gibson
        ;
1339 f2ad6be8 David Gibson
    }
1340 f2ad6be8 David Gibson
1341 8cbbe385 Blue Swirl
    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0)) {
1342 8cbbe385 Blue Swirl
        return -1;
1343 8cbbe385 Blue Swirl
    }
1344 8cbbe385 Blue Swirl
1345 8cbbe385 Blue Swirl
    return ctx.raddr & TARGET_PAGE_MASK;
1346 8cbbe385 Blue Swirl
}
1347 8cbbe385 Blue Swirl
1348 8cbbe385 Blue Swirl
static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
1349 8cbbe385 Blue Swirl
                                     int rw)
1350 8cbbe385 Blue Swirl
{
1351 8cbbe385 Blue Swirl
    env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1352 8cbbe385 Blue Swirl
    env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1353 8cbbe385 Blue Swirl
    env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1354 8cbbe385 Blue Swirl
    env->spr[SPR_BOOKE_MAS3] = 0;
1355 8cbbe385 Blue Swirl
    env->spr[SPR_BOOKE_MAS6] = 0;
1356 8cbbe385 Blue Swirl
    env->spr[SPR_BOOKE_MAS7] = 0;
1357 8cbbe385 Blue Swirl
1358 8cbbe385 Blue Swirl
    /* AS */
1359 8cbbe385 Blue Swirl
    if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
1360 8cbbe385 Blue Swirl
        env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1361 8cbbe385 Blue Swirl
        env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1362 8cbbe385 Blue Swirl
    }
1363 8cbbe385 Blue Swirl
1364 8cbbe385 Blue Swirl
    env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1365 8cbbe385 Blue Swirl
    env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1366 8cbbe385 Blue Swirl
1367 8cbbe385 Blue Swirl
    switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1368 8cbbe385 Blue Swirl
    case MAS4_TIDSELD_PID0:
1369 8cbbe385 Blue Swirl
        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
1370 8cbbe385 Blue Swirl
        break;
1371 8cbbe385 Blue Swirl
    case MAS4_TIDSELD_PID1:
1372 8cbbe385 Blue Swirl
        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
1373 8cbbe385 Blue Swirl
        break;
1374 8cbbe385 Blue Swirl
    case MAS4_TIDSELD_PID2:
1375 8cbbe385 Blue Swirl
        env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
1376 8cbbe385 Blue Swirl
        break;
1377 8cbbe385 Blue Swirl
    }
1378 8cbbe385 Blue Swirl
1379 8cbbe385 Blue Swirl
    env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1380 8cbbe385 Blue Swirl
1381 8cbbe385 Blue Swirl
    /* next victim logic */
1382 8cbbe385 Blue Swirl
    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1383 8cbbe385 Blue Swirl
    env->last_way++;
1384 8cbbe385 Blue Swirl
    env->last_way &= booke206_tlb_ways(env, 0) - 1;
1385 8cbbe385 Blue Swirl
    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1386 8cbbe385 Blue Swirl
}
1387 8cbbe385 Blue Swirl
1388 8cbbe385 Blue Swirl
/* Perform address translation */
1389 eb20c1c6 David Gibson
static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
1390 eb20c1c6 David Gibson
                                    int rw, int mmu_idx)
1391 8cbbe385 Blue Swirl
{
1392 8cbbe385 Blue Swirl
    mmu_ctx_t ctx;
1393 8cbbe385 Blue Swirl
    int access_type;
1394 8cbbe385 Blue Swirl
    int ret = 0;
1395 8cbbe385 Blue Swirl
1396 8cbbe385 Blue Swirl
    if (rw == 2) {
1397 8cbbe385 Blue Swirl
        /* code access */
1398 8cbbe385 Blue Swirl
        rw = 0;
1399 8cbbe385 Blue Swirl
        access_type = ACCESS_CODE;
1400 8cbbe385 Blue Swirl
    } else {
1401 8cbbe385 Blue Swirl
        /* data access */
1402 8cbbe385 Blue Swirl
        access_type = env->access_type;
1403 8cbbe385 Blue Swirl
    }
1404 8cbbe385 Blue Swirl
    ret = get_physical_address(env, &ctx, address, rw, access_type);
1405 8cbbe385 Blue Swirl
    if (ret == 0) {
1406 8cbbe385 Blue Swirl
        tlb_set_page(env, address & TARGET_PAGE_MASK,
1407 8cbbe385 Blue Swirl
                     ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1408 8cbbe385 Blue Swirl
                     mmu_idx, TARGET_PAGE_SIZE);
1409 8cbbe385 Blue Swirl
        ret = 0;
1410 8cbbe385 Blue Swirl
    } else if (ret < 0) {
1411 8cbbe385 Blue Swirl
        LOG_MMU_STATE(env);
1412 8cbbe385 Blue Swirl
        if (access_type == ACCESS_CODE) {
1413 8cbbe385 Blue Swirl
            switch (ret) {
1414 8cbbe385 Blue Swirl
            case -1:
1415 8cbbe385 Blue Swirl
                /* No matches in page tables or TLB */
1416 8cbbe385 Blue Swirl
                switch (env->mmu_model) {
1417 8cbbe385 Blue Swirl
                case POWERPC_MMU_SOFT_6xx:
1418 8cbbe385 Blue Swirl
                    env->exception_index = POWERPC_EXCP_IFTLB;
1419 8cbbe385 Blue Swirl
                    env->error_code = 1 << 18;
1420 8cbbe385 Blue Swirl
                    env->spr[SPR_IMISS] = address;
1421 8cbbe385 Blue Swirl
                    env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1422 8cbbe385 Blue Swirl
                    goto tlb_miss;
1423 8cbbe385 Blue Swirl
                case POWERPC_MMU_SOFT_74xx:
1424 8cbbe385 Blue Swirl
                    env->exception_index = POWERPC_EXCP_IFTLB;
1425 8cbbe385 Blue Swirl
                    goto tlb_miss_74xx;
1426 8cbbe385 Blue Swirl
                case POWERPC_MMU_SOFT_4xx:
1427 8cbbe385 Blue Swirl
                case POWERPC_MMU_SOFT_4xx_Z:
1428 8cbbe385 Blue Swirl
                    env->exception_index = POWERPC_EXCP_ITLB;
1429 8cbbe385 Blue Swirl
                    env->error_code = 0;
1430 8cbbe385 Blue Swirl
                    env->spr[SPR_40x_DEAR] = address;
1431 8cbbe385 Blue Swirl
                    env->spr[SPR_40x_ESR] = 0x00000000;
1432 8cbbe385 Blue Swirl
                    break;
1433 8cbbe385 Blue Swirl
                case POWERPC_MMU_BOOKE206:
1434 8cbbe385 Blue Swirl
                    booke206_update_mas_tlb_miss(env, address, rw);
1435 8cbbe385 Blue Swirl
                    /* fall through */
1436 8cbbe385 Blue Swirl
                case POWERPC_MMU_BOOKE:
1437 8cbbe385 Blue Swirl
                    env->exception_index = POWERPC_EXCP_ITLB;
1438 8cbbe385 Blue Swirl
                    env->error_code = 0;
1439 8cbbe385 Blue Swirl
                    env->spr[SPR_BOOKE_DEAR] = address;
1440 8cbbe385 Blue Swirl
                    return -1;
1441 8cbbe385 Blue Swirl
                case POWERPC_MMU_MPC8xx:
1442 8cbbe385 Blue Swirl
                    /* XXX: TODO */
1443 8cbbe385 Blue Swirl
                    cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1444 8cbbe385 Blue Swirl
                    break;
1445 8cbbe385 Blue Swirl
                case POWERPC_MMU_REAL:
1446 8cbbe385 Blue Swirl
                    cpu_abort(env, "PowerPC in real mode should never raise "
1447 8cbbe385 Blue Swirl
                              "any MMU exceptions\n");
1448 8cbbe385 Blue Swirl
                    return -1;
1449 8cbbe385 Blue Swirl
                default:
1450 8cbbe385 Blue Swirl
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1451 8cbbe385 Blue Swirl
                    return -1;
1452 8cbbe385 Blue Swirl
                }
1453 8cbbe385 Blue Swirl
                break;
1454 8cbbe385 Blue Swirl
            case -2:
1455 8cbbe385 Blue Swirl
                /* Access rights violation */
1456 8cbbe385 Blue Swirl
                env->exception_index = POWERPC_EXCP_ISI;
1457 8cbbe385 Blue Swirl
                env->error_code = 0x08000000;
1458 8cbbe385 Blue Swirl
                break;
1459 8cbbe385 Blue Swirl
            case -3:
1460 8cbbe385 Blue Swirl
                /* No execute protection violation */
1461 8cbbe385 Blue Swirl
                if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1462 8cbbe385 Blue Swirl
                    (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1463 8cbbe385 Blue Swirl
                    env->spr[SPR_BOOKE_ESR] = 0x00000000;
1464 8cbbe385 Blue Swirl
                }
1465 8cbbe385 Blue Swirl
                env->exception_index = POWERPC_EXCP_ISI;
1466 8cbbe385 Blue Swirl
                env->error_code = 0x10000000;
1467 8cbbe385 Blue Swirl
                break;
1468 8cbbe385 Blue Swirl
            case -4:
1469 8cbbe385 Blue Swirl
                /* Direct store exception */
1470 8cbbe385 Blue Swirl
                /* No code fetch is allowed in direct-store areas */
1471 8cbbe385 Blue Swirl
                env->exception_index = POWERPC_EXCP_ISI;
1472 8cbbe385 Blue Swirl
                env->error_code = 0x10000000;
1473 8cbbe385 Blue Swirl
                break;
1474 8cbbe385 Blue Swirl
            }
1475 8cbbe385 Blue Swirl
        } else {
1476 8cbbe385 Blue Swirl
            switch (ret) {
1477 8cbbe385 Blue Swirl
            case -1:
1478 8cbbe385 Blue Swirl
                /* No matches in page tables or TLB */
1479 8cbbe385 Blue Swirl
                switch (env->mmu_model) {
1480 8cbbe385 Blue Swirl
                case POWERPC_MMU_SOFT_6xx:
1481 8cbbe385 Blue Swirl
                    if (rw == 1) {
1482 8cbbe385 Blue Swirl
                        env->exception_index = POWERPC_EXCP_DSTLB;
1483 8cbbe385 Blue Swirl
                        env->error_code = 1 << 16;
1484 8cbbe385 Blue Swirl
                    } else {
1485 8cbbe385 Blue Swirl
                        env->exception_index = POWERPC_EXCP_DLTLB;
1486 8cbbe385 Blue Swirl
                        env->error_code = 0;
1487 8cbbe385 Blue Swirl
                    }
1488 8cbbe385 Blue Swirl
                    env->spr[SPR_DMISS] = address;
1489 8cbbe385 Blue Swirl
                    env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1490 8cbbe385 Blue Swirl
                tlb_miss:
1491 8cbbe385 Blue Swirl
                    env->error_code |= ctx.key << 19;
1492 8cbbe385 Blue Swirl
                    env->spr[SPR_HASH1] = env->htab_base +
1493 59191721 David Gibson
                        get_pteg_offset32(env, ctx.hash[0]);
1494 8cbbe385 Blue Swirl
                    env->spr[SPR_HASH2] = env->htab_base +
1495 59191721 David Gibson
                        get_pteg_offset32(env, ctx.hash[1]);
1496 8cbbe385 Blue Swirl
                    break;
1497 8cbbe385 Blue Swirl
                case POWERPC_MMU_SOFT_74xx:
1498 8cbbe385 Blue Swirl
                    if (rw == 1) {
1499 8cbbe385 Blue Swirl
                        env->exception_index = POWERPC_EXCP_DSTLB;
1500 8cbbe385 Blue Swirl
                    } else {
1501 8cbbe385 Blue Swirl
                        env->exception_index = POWERPC_EXCP_DLTLB;
1502 8cbbe385 Blue Swirl
                    }
1503 8cbbe385 Blue Swirl
                tlb_miss_74xx:
1504 8cbbe385 Blue Swirl
                    /* Implement LRU algorithm */
1505 8cbbe385 Blue Swirl
                    env->error_code = ctx.key << 19;
1506 8cbbe385 Blue Swirl
                    env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1507 8cbbe385 Blue Swirl
                        ((env->last_way + 1) & (env->nb_ways - 1));
1508 8cbbe385 Blue Swirl
                    env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1509 8cbbe385 Blue Swirl
                    break;
1510 8cbbe385 Blue Swirl
                case POWERPC_MMU_SOFT_4xx:
1511 8cbbe385 Blue Swirl
                case POWERPC_MMU_SOFT_4xx_Z:
1512 8cbbe385 Blue Swirl
                    env->exception_index = POWERPC_EXCP_DTLB;
1513 8cbbe385 Blue Swirl
                    env->error_code = 0;
1514 8cbbe385 Blue Swirl
                    env->spr[SPR_40x_DEAR] = address;
1515 8cbbe385 Blue Swirl
                    if (rw) {
1516 8cbbe385 Blue Swirl
                        env->spr[SPR_40x_ESR] = 0x00800000;
1517 8cbbe385 Blue Swirl
                    } else {
1518 8cbbe385 Blue Swirl
                        env->spr[SPR_40x_ESR] = 0x00000000;
1519 8cbbe385 Blue Swirl
                    }
1520 8cbbe385 Blue Swirl
                    break;
1521 8cbbe385 Blue Swirl
                case POWERPC_MMU_MPC8xx:
1522 8cbbe385 Blue Swirl
                    /* XXX: TODO */
1523 8cbbe385 Blue Swirl
                    cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1524 8cbbe385 Blue Swirl
                    break;
1525 8cbbe385 Blue Swirl
                case POWERPC_MMU_BOOKE206:
1526 8cbbe385 Blue Swirl
                    booke206_update_mas_tlb_miss(env, address, rw);
1527 8cbbe385 Blue Swirl
                    /* fall through */
1528 8cbbe385 Blue Swirl
                case POWERPC_MMU_BOOKE:
1529 8cbbe385 Blue Swirl
                    env->exception_index = POWERPC_EXCP_DTLB;
1530 8cbbe385 Blue Swirl
                    env->error_code = 0;
1531 8cbbe385 Blue Swirl
                    env->spr[SPR_BOOKE_DEAR] = address;
1532 8cbbe385 Blue Swirl
                    env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1533 8cbbe385 Blue Swirl
                    return -1;
1534 8cbbe385 Blue Swirl
                case POWERPC_MMU_REAL:
1535 8cbbe385 Blue Swirl
                    cpu_abort(env, "PowerPC in real mode should never raise "
1536 8cbbe385 Blue Swirl
                              "any MMU exceptions\n");
1537 8cbbe385 Blue Swirl
                    return -1;
1538 8cbbe385 Blue Swirl
                default:
1539 8cbbe385 Blue Swirl
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1540 8cbbe385 Blue Swirl
                    return -1;
1541 8cbbe385 Blue Swirl
                }
1542 8cbbe385 Blue Swirl
                break;
1543 8cbbe385 Blue Swirl
            case -2:
1544 8cbbe385 Blue Swirl
                /* Access rights violation */
1545 8cbbe385 Blue Swirl
                env->exception_index = POWERPC_EXCP_DSI;
1546 8cbbe385 Blue Swirl
                env->error_code = 0;
1547 8cbbe385 Blue Swirl
                if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1548 8cbbe385 Blue Swirl
                    || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1549 8cbbe385 Blue Swirl
                    env->spr[SPR_40x_DEAR] = address;
1550 8cbbe385 Blue Swirl
                    if (rw) {
1551 8cbbe385 Blue Swirl
                        env->spr[SPR_40x_ESR] |= 0x00800000;
1552 8cbbe385 Blue Swirl
                    }
1553 8cbbe385 Blue Swirl
                } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1554 8cbbe385 Blue Swirl
                           (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1555 8cbbe385 Blue Swirl
                    env->spr[SPR_BOOKE_DEAR] = address;
1556 8cbbe385 Blue Swirl
                    env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1557 8cbbe385 Blue Swirl
                } else {
1558 8cbbe385 Blue Swirl
                    env->spr[SPR_DAR] = address;
1559 8cbbe385 Blue Swirl
                    if (rw == 1) {
1560 8cbbe385 Blue Swirl
                        env->spr[SPR_DSISR] = 0x0A000000;
1561 8cbbe385 Blue Swirl
                    } else {
1562 8cbbe385 Blue Swirl
                        env->spr[SPR_DSISR] = 0x08000000;
1563 8cbbe385 Blue Swirl
                    }
1564 8cbbe385 Blue Swirl
                }
1565 8cbbe385 Blue Swirl
                break;
1566 8cbbe385 Blue Swirl
            case -4:
1567 8cbbe385 Blue Swirl
                /* Direct store exception */
1568 8cbbe385 Blue Swirl
                switch (access_type) {
1569 8cbbe385 Blue Swirl
                case ACCESS_FLOAT:
1570 8cbbe385 Blue Swirl
                    /* Floating point load/store */
1571 8cbbe385 Blue Swirl
                    env->exception_index = POWERPC_EXCP_ALIGN;
1572 8cbbe385 Blue Swirl
                    env->error_code = POWERPC_EXCP_ALIGN_FP;
1573 8cbbe385 Blue Swirl
                    env->spr[SPR_DAR] = address;
1574 8cbbe385 Blue Swirl
                    break;
1575 8cbbe385 Blue Swirl
                case ACCESS_RES:
1576 8cbbe385 Blue Swirl
                    /* lwarx, ldarx or stwcx. */
1577 8cbbe385 Blue Swirl
                    env->exception_index = POWERPC_EXCP_DSI;
1578 8cbbe385 Blue Swirl
                    env->error_code = 0;
1579 8cbbe385 Blue Swirl
                    env->spr[SPR_DAR] = address;
1580 8cbbe385 Blue Swirl
                    if (rw == 1) {
1581 8cbbe385 Blue Swirl
                        env->spr[SPR_DSISR] = 0x06000000;
1582 8cbbe385 Blue Swirl
                    } else {
1583 8cbbe385 Blue Swirl
                        env->spr[SPR_DSISR] = 0x04000000;
1584 8cbbe385 Blue Swirl
                    }
1585 8cbbe385 Blue Swirl
                    break;
1586 8cbbe385 Blue Swirl
                case ACCESS_EXT:
1587 8cbbe385 Blue Swirl
                    /* eciwx or ecowx */
1588 8cbbe385 Blue Swirl
                    env->exception_index = POWERPC_EXCP_DSI;
1589 8cbbe385 Blue Swirl
                    env->error_code = 0;
1590 8cbbe385 Blue Swirl
                    env->spr[SPR_DAR] = address;
1591 8cbbe385 Blue Swirl
                    if (rw == 1) {
1592 8cbbe385 Blue Swirl
                        env->spr[SPR_DSISR] = 0x06100000;
1593 8cbbe385 Blue Swirl
                    } else {
1594 8cbbe385 Blue Swirl
                        env->spr[SPR_DSISR] = 0x04100000;
1595 8cbbe385 Blue Swirl
                    }
1596 8cbbe385 Blue Swirl
                    break;
1597 8cbbe385 Blue Swirl
                default:
1598 8cbbe385 Blue Swirl
                    printf("DSI: invalid exception (%d)\n", ret);
1599 8cbbe385 Blue Swirl
                    env->exception_index = POWERPC_EXCP_PROGRAM;
1600 8cbbe385 Blue Swirl
                    env->error_code =
1601 8cbbe385 Blue Swirl
                        POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1602 8cbbe385 Blue Swirl
                    env->spr[SPR_DAR] = address;
1603 8cbbe385 Blue Swirl
                    break;
1604 8cbbe385 Blue Swirl
                }
1605 8cbbe385 Blue Swirl
                break;
1606 8cbbe385 Blue Swirl
            }
1607 8cbbe385 Blue Swirl
        }
1608 8cbbe385 Blue Swirl
#if 0
1609 8cbbe385 Blue Swirl
        printf("%s: set exception to %d %02x\n", __func__,
1610 8cbbe385 Blue Swirl
               env->exception, env->error_code);
1611 8cbbe385 Blue Swirl
#endif
1612 8cbbe385 Blue Swirl
        ret = 1;
1613 8cbbe385 Blue Swirl
    }
1614 8cbbe385 Blue Swirl
1615 8cbbe385 Blue Swirl
    return ret;
1616 8cbbe385 Blue Swirl
}
1617 8cbbe385 Blue Swirl
1618 8cbbe385 Blue Swirl
/*****************************************************************************/
1619 8cbbe385 Blue Swirl
/* BATs management */
1620 8cbbe385 Blue Swirl
#if !defined(FLUSH_ALL_TLBS)
1621 8cbbe385 Blue Swirl
static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1622 8cbbe385 Blue Swirl
                                     target_ulong mask)
1623 8cbbe385 Blue Swirl
{
1624 8cbbe385 Blue Swirl
    target_ulong base, end, page;
1625 8cbbe385 Blue Swirl
1626 8cbbe385 Blue Swirl
    base = BATu & ~0x0001FFFF;
1627 8cbbe385 Blue Swirl
    end = base + mask + 0x00020000;
1628 8cbbe385 Blue Swirl
    LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1629 8cbbe385 Blue Swirl
             TARGET_FMT_lx ")\n", base, end, mask);
1630 8cbbe385 Blue Swirl
    for (page = base; page != end; page += TARGET_PAGE_SIZE) {
1631 8cbbe385 Blue Swirl
        tlb_flush_page(env, page);
1632 8cbbe385 Blue Swirl
    }
1633 8cbbe385 Blue Swirl
    LOG_BATS("Flush done\n");
1634 8cbbe385 Blue Swirl
}
1635 8cbbe385 Blue Swirl
#endif
1636 8cbbe385 Blue Swirl
1637 8cbbe385 Blue Swirl
static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1638 8cbbe385 Blue Swirl
                                  target_ulong value)
1639 8cbbe385 Blue Swirl
{
1640 8cbbe385 Blue Swirl
    LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1641 8cbbe385 Blue Swirl
             nr, ul == 0 ? 'u' : 'l', value, env->nip);
1642 8cbbe385 Blue Swirl
}
1643 8cbbe385 Blue Swirl
1644 9aa5b158 Blue Swirl
void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1645 8cbbe385 Blue Swirl
{
1646 8cbbe385 Blue Swirl
    target_ulong mask;
1647 8cbbe385 Blue Swirl
1648 8cbbe385 Blue Swirl
    dump_store_bat(env, 'I', 0, nr, value);
1649 8cbbe385 Blue Swirl
    if (env->IBAT[0][nr] != value) {
1650 8cbbe385 Blue Swirl
        mask = (value << 15) & 0x0FFE0000UL;
1651 8cbbe385 Blue Swirl
#if !defined(FLUSH_ALL_TLBS)
1652 8cbbe385 Blue Swirl
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1653 8cbbe385 Blue Swirl
#endif
1654 8cbbe385 Blue Swirl
        /* When storing valid upper BAT, mask BEPI and BRPN
1655 8cbbe385 Blue Swirl
         * and invalidate all TLBs covered by this BAT
1656 8cbbe385 Blue Swirl
         */
1657 8cbbe385 Blue Swirl
        mask = (value << 15) & 0x0FFE0000UL;
1658 8cbbe385 Blue Swirl
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1659 8cbbe385 Blue Swirl
            (value & ~0x0001FFFFUL & ~mask);
1660 8cbbe385 Blue Swirl
        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1661 8cbbe385 Blue Swirl
            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1662 8cbbe385 Blue Swirl
#if !defined(FLUSH_ALL_TLBS)
1663 8cbbe385 Blue Swirl
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1664 8cbbe385 Blue Swirl
#else
1665 8cbbe385 Blue Swirl
        tlb_flush(env, 1);
1666 8cbbe385 Blue Swirl
#endif
1667 8cbbe385 Blue Swirl
    }
1668 8cbbe385 Blue Swirl
}
1669 8cbbe385 Blue Swirl
1670 9aa5b158 Blue Swirl
void helper_store_ibatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1671 8cbbe385 Blue Swirl
{
1672 8cbbe385 Blue Swirl
    dump_store_bat(env, 'I', 1, nr, value);
1673 8cbbe385 Blue Swirl
    env->IBAT[1][nr] = value;
1674 8cbbe385 Blue Swirl
}
1675 8cbbe385 Blue Swirl
1676 9aa5b158 Blue Swirl
void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1677 8cbbe385 Blue Swirl
{
1678 8cbbe385 Blue Swirl
    target_ulong mask;
1679 8cbbe385 Blue Swirl
1680 8cbbe385 Blue Swirl
    dump_store_bat(env, 'D', 0, nr, value);
1681 8cbbe385 Blue Swirl
    if (env->DBAT[0][nr] != value) {
1682 8cbbe385 Blue Swirl
        /* When storing valid upper BAT, mask BEPI and BRPN
1683 8cbbe385 Blue Swirl
         * and invalidate all TLBs covered by this BAT
1684 8cbbe385 Blue Swirl
         */
1685 8cbbe385 Blue Swirl
        mask = (value << 15) & 0x0FFE0000UL;
1686 8cbbe385 Blue Swirl
#if !defined(FLUSH_ALL_TLBS)
1687 8cbbe385 Blue Swirl
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1688 8cbbe385 Blue Swirl
#endif
1689 8cbbe385 Blue Swirl
        mask = (value << 15) & 0x0FFE0000UL;
1690 8cbbe385 Blue Swirl
        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1691 8cbbe385 Blue Swirl
            (value & ~0x0001FFFFUL & ~mask);
1692 8cbbe385 Blue Swirl
        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1693 8cbbe385 Blue Swirl
            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1694 8cbbe385 Blue Swirl
#if !defined(FLUSH_ALL_TLBS)
1695 8cbbe385 Blue Swirl
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1696 8cbbe385 Blue Swirl
#else
1697 8cbbe385 Blue Swirl
        tlb_flush(env, 1);
1698 8cbbe385 Blue Swirl
#endif
1699 8cbbe385 Blue Swirl
    }
1700 8cbbe385 Blue Swirl
}
1701 8cbbe385 Blue Swirl
1702 9aa5b158 Blue Swirl
void helper_store_dbatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1703 8cbbe385 Blue Swirl
{
1704 8cbbe385 Blue Swirl
    dump_store_bat(env, 'D', 1, nr, value);
1705 8cbbe385 Blue Swirl
    env->DBAT[1][nr] = value;
1706 8cbbe385 Blue Swirl
}
1707 8cbbe385 Blue Swirl
1708 9aa5b158 Blue Swirl
void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
1709 8cbbe385 Blue Swirl
{
1710 8cbbe385 Blue Swirl
    target_ulong mask;
1711 8cbbe385 Blue Swirl
#if defined(FLUSH_ALL_TLBS)
1712 8cbbe385 Blue Swirl
    int do_inval;
1713 8cbbe385 Blue Swirl
#endif
1714 8cbbe385 Blue Swirl
1715 8cbbe385 Blue Swirl
    dump_store_bat(env, 'I', 0, nr, value);
1716 8cbbe385 Blue Swirl
    if (env->IBAT[0][nr] != value) {
1717 8cbbe385 Blue Swirl
#if defined(FLUSH_ALL_TLBS)
1718 8cbbe385 Blue Swirl
        do_inval = 0;
1719 8cbbe385 Blue Swirl
#endif
1720 8cbbe385 Blue Swirl
        mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1721 8cbbe385 Blue Swirl
        if (env->IBAT[1][nr] & 0x40) {
1722 8cbbe385 Blue Swirl
            /* Invalidate BAT only if it is valid */
1723 8cbbe385 Blue Swirl
#if !defined(FLUSH_ALL_TLBS)
1724 8cbbe385 Blue Swirl
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1725 8cbbe385 Blue Swirl
#else
1726 8cbbe385 Blue Swirl
            do_inval = 1;
1727 8cbbe385 Blue Swirl
#endif
1728 8cbbe385 Blue Swirl
        }
1729 8cbbe385 Blue Swirl
        /* When storing valid upper BAT, mask BEPI and BRPN
1730 8cbbe385 Blue Swirl
         * and invalidate all TLBs covered by this BAT
1731 8cbbe385 Blue Swirl
         */
1732 8cbbe385 Blue Swirl
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1733 8cbbe385 Blue Swirl
            (value & ~0x0001FFFFUL & ~mask);
1734 8cbbe385 Blue Swirl
        env->DBAT[0][nr] = env->IBAT[0][nr];
1735 8cbbe385 Blue Swirl
        if (env->IBAT[1][nr] & 0x40) {
1736 8cbbe385 Blue Swirl
#if !defined(FLUSH_ALL_TLBS)
1737 8cbbe385 Blue Swirl
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1738 8cbbe385 Blue Swirl
#else
1739 8cbbe385 Blue Swirl
            do_inval = 1;
1740 8cbbe385 Blue Swirl
#endif
1741 8cbbe385 Blue Swirl
        }
1742 8cbbe385 Blue Swirl
#if defined(FLUSH_ALL_TLBS)
1743 8cbbe385 Blue Swirl
        if (do_inval) {
1744 8cbbe385 Blue Swirl
            tlb_flush(env, 1);
1745 8cbbe385 Blue Swirl
        }
1746 8cbbe385 Blue Swirl
#endif
1747 8cbbe385 Blue Swirl
    }
1748 8cbbe385 Blue Swirl
}
1749 8cbbe385 Blue Swirl
1750 9aa5b158 Blue Swirl
void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
1751 8cbbe385 Blue Swirl
{
1752 cca48a93 Andreas Fรคrber
#if !defined(FLUSH_ALL_TLBS)
1753 8cbbe385 Blue Swirl
    target_ulong mask;
1754 cca48a93 Andreas Fรคrber
#else
1755 8cbbe385 Blue Swirl
    int do_inval;
1756 8cbbe385 Blue Swirl
#endif
1757 8cbbe385 Blue Swirl
1758 8cbbe385 Blue Swirl
    dump_store_bat(env, 'I', 1, nr, value);
1759 8cbbe385 Blue Swirl
    if (env->IBAT[1][nr] != value) {
1760 8cbbe385 Blue Swirl
#if defined(FLUSH_ALL_TLBS)
1761 8cbbe385 Blue Swirl
        do_inval = 0;
1762 8cbbe385 Blue Swirl
#endif
1763 8cbbe385 Blue Swirl
        if (env->IBAT[1][nr] & 0x40) {
1764 8cbbe385 Blue Swirl
#if !defined(FLUSH_ALL_TLBS)
1765 8cbbe385 Blue Swirl
            mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1766 8cbbe385 Blue Swirl
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1767 8cbbe385 Blue Swirl
#else
1768 8cbbe385 Blue Swirl
            do_inval = 1;
1769 8cbbe385 Blue Swirl
#endif
1770 8cbbe385 Blue Swirl
        }
1771 8cbbe385 Blue Swirl
        if (value & 0x40) {
1772 8cbbe385 Blue Swirl
#if !defined(FLUSH_ALL_TLBS)
1773 8cbbe385 Blue Swirl
            mask = (value << 17) & 0x0FFE0000UL;
1774 8cbbe385 Blue Swirl
            do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1775 8cbbe385 Blue Swirl
#else
1776 8cbbe385 Blue Swirl
            do_inval = 1;
1777 8cbbe385 Blue Swirl
#endif
1778 8cbbe385 Blue Swirl
        }
1779 8cbbe385 Blue Swirl
        env->IBAT[1][nr] = value;
1780 8cbbe385 Blue Swirl
        env->DBAT[1][nr] = value;
1781 8cbbe385 Blue Swirl
#if defined(FLUSH_ALL_TLBS)
1782 8cbbe385 Blue Swirl
        if (do_inval) {
1783 8cbbe385 Blue Swirl
            tlb_flush(env, 1);
1784 8cbbe385 Blue Swirl
        }
1785 8cbbe385 Blue Swirl
#endif
1786 8cbbe385 Blue Swirl
    }
1787 8cbbe385 Blue Swirl
}
1788 8cbbe385 Blue Swirl
1789 8cbbe385 Blue Swirl
/*****************************************************************************/
1790 8cbbe385 Blue Swirl
/* TLB management */
1791 8cbbe385 Blue Swirl
void ppc_tlb_invalidate_all(CPUPPCState *env)
1792 8cbbe385 Blue Swirl
{
1793 8cbbe385 Blue Swirl
    switch (env->mmu_model) {
1794 8cbbe385 Blue Swirl
    case POWERPC_MMU_SOFT_6xx:
1795 8cbbe385 Blue Swirl
    case POWERPC_MMU_SOFT_74xx:
1796 8cbbe385 Blue Swirl
        ppc6xx_tlb_invalidate_all(env);
1797 8cbbe385 Blue Swirl
        break;
1798 8cbbe385 Blue Swirl
    case POWERPC_MMU_SOFT_4xx:
1799 8cbbe385 Blue Swirl
    case POWERPC_MMU_SOFT_4xx_Z:
1800 8cbbe385 Blue Swirl
        ppc4xx_tlb_invalidate_all(env);
1801 8cbbe385 Blue Swirl
        break;
1802 8cbbe385 Blue Swirl
    case POWERPC_MMU_REAL:
1803 8cbbe385 Blue Swirl
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1804 8cbbe385 Blue Swirl
        break;
1805 8cbbe385 Blue Swirl
    case POWERPC_MMU_MPC8xx:
1806 8cbbe385 Blue Swirl
        /* XXX: TODO */
1807 8cbbe385 Blue Swirl
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1808 8cbbe385 Blue Swirl
        break;
1809 8cbbe385 Blue Swirl
    case POWERPC_MMU_BOOKE:
1810 8cbbe385 Blue Swirl
        tlb_flush(env, 1);
1811 8cbbe385 Blue Swirl
        break;
1812 8cbbe385 Blue Swirl
    case POWERPC_MMU_BOOKE206:
1813 8cbbe385 Blue Swirl
        booke206_flush_tlb(env, -1, 0);
1814 8cbbe385 Blue Swirl
        break;
1815 8cbbe385 Blue Swirl
    case POWERPC_MMU_32B:
1816 8cbbe385 Blue Swirl
    case POWERPC_MMU_601:
1817 8cbbe385 Blue Swirl
#if defined(TARGET_PPC64)
1818 8cbbe385 Blue Swirl
    case POWERPC_MMU_64B:
1819 8cbbe385 Blue Swirl
    case POWERPC_MMU_2_06:
1820 126a7930 Alexander Graf
    case POWERPC_MMU_2_06a:
1821 4656e1f0 Benjamin Herrenschmidt
    case POWERPC_MMU_2_06d:
1822 8cbbe385 Blue Swirl
#endif /* defined(TARGET_PPC64) */
1823 8cbbe385 Blue Swirl
        tlb_flush(env, 1);
1824 8cbbe385 Blue Swirl
        break;
1825 8cbbe385 Blue Swirl
    default:
1826 8cbbe385 Blue Swirl
        /* XXX: TODO */
1827 8cbbe385 Blue Swirl
        cpu_abort(env, "Unknown MMU model\n");
1828 8cbbe385 Blue Swirl
        break;
1829 8cbbe385 Blue Swirl
    }
1830 8cbbe385 Blue Swirl
}
1831 8cbbe385 Blue Swirl
1832 8cbbe385 Blue Swirl
void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
1833 8cbbe385 Blue Swirl
{
1834 8cbbe385 Blue Swirl
#if !defined(FLUSH_ALL_TLBS)
1835 8cbbe385 Blue Swirl
    addr &= TARGET_PAGE_MASK;
1836 8cbbe385 Blue Swirl
    switch (env->mmu_model) {
1837 8cbbe385 Blue Swirl
    case POWERPC_MMU_SOFT_6xx:
1838 8cbbe385 Blue Swirl
    case POWERPC_MMU_SOFT_74xx:
1839 8cbbe385 Blue Swirl
        ppc6xx_tlb_invalidate_virt(env, addr, 0);
1840 8cbbe385 Blue Swirl
        if (env->id_tlbs == 1) {
1841 8cbbe385 Blue Swirl
            ppc6xx_tlb_invalidate_virt(env, addr, 1);
1842 8cbbe385 Blue Swirl
        }
1843 8cbbe385 Blue Swirl
        break;
1844 8cbbe385 Blue Swirl
    case POWERPC_MMU_SOFT_4xx:
1845 8cbbe385 Blue Swirl
    case POWERPC_MMU_SOFT_4xx_Z:
1846 8cbbe385 Blue Swirl
        ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
1847 8cbbe385 Blue Swirl
        break;
1848 8cbbe385 Blue Swirl
    case POWERPC_MMU_REAL:
1849 8cbbe385 Blue Swirl
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1850 8cbbe385 Blue Swirl
        break;
1851 8cbbe385 Blue Swirl
    case POWERPC_MMU_MPC8xx:
1852 8cbbe385 Blue Swirl
        /* XXX: TODO */
1853 8cbbe385 Blue Swirl
        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1854 8cbbe385 Blue Swirl
        break;
1855 8cbbe385 Blue Swirl
    case POWERPC_MMU_BOOKE:
1856 8cbbe385 Blue Swirl
        /* XXX: TODO */
1857 8cbbe385 Blue Swirl
        cpu_abort(env, "BookE MMU model is not implemented\n");
1858 8cbbe385 Blue Swirl
        break;
1859 8cbbe385 Blue Swirl
    case POWERPC_MMU_BOOKE206:
1860 8cbbe385 Blue Swirl
        /* XXX: TODO */
1861 8cbbe385 Blue Swirl
        cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
1862 8cbbe385 Blue Swirl
        break;
1863 8cbbe385 Blue Swirl
    case POWERPC_MMU_32B:
1864 8cbbe385 Blue Swirl
    case POWERPC_MMU_601:
1865 8cbbe385 Blue Swirl
        /* tlbie invalidate TLBs for all segments */
1866 8cbbe385 Blue Swirl
        addr &= ~((target_ulong)-1ULL << 28);
1867 8cbbe385 Blue Swirl
        /* XXX: this case should be optimized,
1868 8cbbe385 Blue Swirl
         * giving a mask to tlb_flush_page
1869 8cbbe385 Blue Swirl
         */
1870 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0x0 << 28));
1871 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0x1 << 28));
1872 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0x2 << 28));
1873 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0x3 << 28));
1874 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0x4 << 28));
1875 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0x5 << 28));
1876 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0x6 << 28));
1877 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0x7 << 28));
1878 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0x8 << 28));
1879 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0x9 << 28));
1880 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0xA << 28));
1881 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0xB << 28));
1882 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0xC << 28));
1883 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0xD << 28));
1884 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0xE << 28));
1885 8cbbe385 Blue Swirl
        tlb_flush_page(env, addr | (0xF << 28));
1886 8cbbe385 Blue Swirl
        break;
1887 8cbbe385 Blue Swirl
#if defined(TARGET_PPC64)
1888 8cbbe385 Blue Swirl
    case POWERPC_MMU_64B:
1889 8cbbe385 Blue Swirl
    case POWERPC_MMU_2_06:
1890 126a7930 Alexander Graf
    case POWERPC_MMU_2_06a:
1891 4656e1f0 Benjamin Herrenschmidt
    case POWERPC_MMU_2_06d:
1892 8cbbe385 Blue Swirl
        /* tlbie invalidate TLBs for all segments */
1893 8cbbe385 Blue Swirl
        /* XXX: given the fact that there are too many segments to invalidate,
1894 8cbbe385 Blue Swirl
         *      and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
1895 8cbbe385 Blue Swirl
         *      we just invalidate all TLBs
1896 8cbbe385 Blue Swirl
         */
1897 8cbbe385 Blue Swirl
        tlb_flush(env, 1);
1898 8cbbe385 Blue Swirl
        break;
1899 8cbbe385 Blue Swirl
#endif /* defined(TARGET_PPC64) */
1900 8cbbe385 Blue Swirl
    default:
1901 8cbbe385 Blue Swirl
        /* XXX: TODO */
1902 8cbbe385 Blue Swirl
        cpu_abort(env, "Unknown MMU model\n");
1903 8cbbe385 Blue Swirl
        break;
1904 8cbbe385 Blue Swirl
    }
1905 8cbbe385 Blue Swirl
#else
1906 8cbbe385 Blue Swirl
    ppc_tlb_invalidate_all(env);
1907 8cbbe385 Blue Swirl
#endif
1908 8cbbe385 Blue Swirl
}
1909 8cbbe385 Blue Swirl
1910 8cbbe385 Blue Swirl
/*****************************************************************************/
1911 8cbbe385 Blue Swirl
/* Special registers manipulation */
1912 8cbbe385 Blue Swirl
void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
1913 8cbbe385 Blue Swirl
{
1914 8cbbe385 Blue Swirl
    LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
1915 8cbbe385 Blue Swirl
    if (env->spr[SPR_SDR1] != value) {
1916 8cbbe385 Blue Swirl
        env->spr[SPR_SDR1] = value;
1917 8cbbe385 Blue Swirl
#if defined(TARGET_PPC64)
1918 8cbbe385 Blue Swirl
        if (env->mmu_model & POWERPC_MMU_64) {
1919 8cbbe385 Blue Swirl
            target_ulong htabsize = value & SDR_64_HTABSIZE;
1920 8cbbe385 Blue Swirl
1921 8cbbe385 Blue Swirl
            if (htabsize > 28) {
1922 8cbbe385 Blue Swirl
                fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
1923 8cbbe385 Blue Swirl
                        " stored in SDR1\n", htabsize);
1924 8cbbe385 Blue Swirl
                htabsize = 28;
1925 8cbbe385 Blue Swirl
            }
1926 8cbbe385 Blue Swirl
            env->htab_mask = (1ULL << (htabsize + 18)) - 1;
1927 8cbbe385 Blue Swirl
            env->htab_base = value & SDR_64_HTABORG;
1928 8cbbe385 Blue Swirl
        } else
1929 8cbbe385 Blue Swirl
#endif /* defined(TARGET_PPC64) */
1930 8cbbe385 Blue Swirl
        {
1931 8cbbe385 Blue Swirl
            /* FIXME: Should check for valid HTABMASK values */
1932 8cbbe385 Blue Swirl
            env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
1933 8cbbe385 Blue Swirl
            env->htab_base = value & SDR_32_HTABORG;
1934 8cbbe385 Blue Swirl
        }
1935 8cbbe385 Blue Swirl
        tlb_flush(env, 1);
1936 8cbbe385 Blue Swirl
    }
1937 8cbbe385 Blue Swirl
}
1938 8cbbe385 Blue Swirl
1939 9aa5b158 Blue Swirl
/* Segment registers load and store */
1940 9aa5b158 Blue Swirl
target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num)
1941 8cbbe385 Blue Swirl
{
1942 9aa5b158 Blue Swirl
#if defined(TARGET_PPC64)
1943 9aa5b158 Blue Swirl
    if (env->mmu_model & POWERPC_MMU_64) {
1944 9aa5b158 Blue Swirl
        /* XXX */
1945 9aa5b158 Blue Swirl
        return 0;
1946 9aa5b158 Blue Swirl
    }
1947 8cbbe385 Blue Swirl
#endif
1948 9aa5b158 Blue Swirl
    return env->sr[sr_num];
1949 9aa5b158 Blue Swirl
}
1950 8cbbe385 Blue Swirl
1951 9aa5b158 Blue Swirl
void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
1952 8cbbe385 Blue Swirl
{
1953 8cbbe385 Blue Swirl
    LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
1954 9aa5b158 Blue Swirl
            (int)srnum, value, env->sr[srnum]);
1955 8cbbe385 Blue Swirl
#if defined(TARGET_PPC64)
1956 8cbbe385 Blue Swirl
    if (env->mmu_model & POWERPC_MMU_64) {
1957 8cbbe385 Blue Swirl
        uint64_t rb = 0, rs = 0;
1958 8cbbe385 Blue Swirl
1959 8cbbe385 Blue Swirl
        /* ESID = srnum */
1960 8cbbe385 Blue Swirl
        rb |= ((uint32_t)srnum & 0xf) << 28;
1961 8cbbe385 Blue Swirl
        /* Set the valid bit */
1962 8cbbe385 Blue Swirl
        rb |= 1 << 27;
1963 8cbbe385 Blue Swirl
        /* Index = ESID */
1964 8cbbe385 Blue Swirl
        rb |= (uint32_t)srnum;
1965 8cbbe385 Blue Swirl
1966 8cbbe385 Blue Swirl
        /* VSID = VSID */
1967 8cbbe385 Blue Swirl
        rs |= (value & 0xfffffff) << 12;
1968 8cbbe385 Blue Swirl
        /* flags = flags */
1969 8cbbe385 Blue Swirl
        rs |= ((value >> 27) & 0xf) << 8;
1970 8cbbe385 Blue Swirl
1971 8cbbe385 Blue Swirl
        ppc_store_slb(env, rb, rs);
1972 8cbbe385 Blue Swirl
    } else
1973 8cbbe385 Blue Swirl
#endif
1974 8cbbe385 Blue Swirl
    if (env->sr[srnum] != value) {
1975 8cbbe385 Blue Swirl
        env->sr[srnum] = value;
1976 8cbbe385 Blue Swirl
/* Invalidating 256MB of virtual memory in 4kB pages is way longer than
1977 8cbbe385 Blue Swirl
   flusing the whole TLB. */
1978 8cbbe385 Blue Swirl
#if !defined(FLUSH_ALL_TLBS) && 0
1979 8cbbe385 Blue Swirl
        {
1980 8cbbe385 Blue Swirl
            target_ulong page, end;
1981 8cbbe385 Blue Swirl
            /* Invalidate 256 MB of virtual memory */
1982 8cbbe385 Blue Swirl
            page = (16 << 20) * srnum;
1983 8cbbe385 Blue Swirl
            end = page + (16 << 20);
1984 8cbbe385 Blue Swirl
            for (; page != end; page += TARGET_PAGE_SIZE) {
1985 8cbbe385 Blue Swirl
                tlb_flush_page(env, page);
1986 8cbbe385 Blue Swirl
            }
1987 8cbbe385 Blue Swirl
        }
1988 8cbbe385 Blue Swirl
#else
1989 8cbbe385 Blue Swirl
        tlb_flush(env, 1);
1990 8cbbe385 Blue Swirl
#endif
1991 8cbbe385 Blue Swirl
    }
1992 8cbbe385 Blue Swirl
}
1993 8cbbe385 Blue Swirl
1994 ec19c4d1 Blue Swirl
/* TLB management */
1995 c6c7cf05 Blue Swirl
void helper_tlbia(CPUPPCState *env)
1996 ec19c4d1 Blue Swirl
{
1997 ec19c4d1 Blue Swirl
    ppc_tlb_invalidate_all(env);
1998 ec19c4d1 Blue Swirl
}
1999 ec19c4d1 Blue Swirl
2000 c6c7cf05 Blue Swirl
void helper_tlbie(CPUPPCState *env, target_ulong addr)
2001 ec19c4d1 Blue Swirl
{
2002 ec19c4d1 Blue Swirl
    ppc_tlb_invalidate_one(env, addr);
2003 ec19c4d1 Blue Swirl
}
2004 ec19c4d1 Blue Swirl
2005 ec19c4d1 Blue Swirl
/* Software driven TLBs management */
2006 ec19c4d1 Blue Swirl
/* PowerPC 602/603 software TLB load instructions helpers */
2007 c6c7cf05 Blue Swirl
static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2008 ec19c4d1 Blue Swirl
{
2009 ec19c4d1 Blue Swirl
    target_ulong RPN, CMP, EPN;
2010 ec19c4d1 Blue Swirl
    int way;
2011 ec19c4d1 Blue Swirl
2012 ec19c4d1 Blue Swirl
    RPN = env->spr[SPR_RPA];
2013 ec19c4d1 Blue Swirl
    if (is_code) {
2014 ec19c4d1 Blue Swirl
        CMP = env->spr[SPR_ICMP];
2015 ec19c4d1 Blue Swirl
        EPN = env->spr[SPR_IMISS];
2016 ec19c4d1 Blue Swirl
    } else {
2017 ec19c4d1 Blue Swirl
        CMP = env->spr[SPR_DCMP];
2018 ec19c4d1 Blue Swirl
        EPN = env->spr[SPR_DMISS];
2019 ec19c4d1 Blue Swirl
    }
2020 ec19c4d1 Blue Swirl
    way = (env->spr[SPR_SRR1] >> 17) & 1;
2021 ec19c4d1 Blue Swirl
    (void)EPN; /* avoid a compiler warning */
2022 ec19c4d1 Blue Swirl
    LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2023 ec19c4d1 Blue Swirl
              " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2024 ec19c4d1 Blue Swirl
              RPN, way);
2025 ec19c4d1 Blue Swirl
    /* Store this TLB */
2026 ec19c4d1 Blue Swirl
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2027 ec19c4d1 Blue Swirl
                     way, is_code, CMP, RPN);
2028 ec19c4d1 Blue Swirl
}
2029 ec19c4d1 Blue Swirl
2030 c6c7cf05 Blue Swirl
void helper_6xx_tlbd(CPUPPCState *env, target_ulong EPN)
2031 ec19c4d1 Blue Swirl
{
2032 c6c7cf05 Blue Swirl
    do_6xx_tlb(env, EPN, 0);
2033 ec19c4d1 Blue Swirl
}
2034 ec19c4d1 Blue Swirl
2035 c6c7cf05 Blue Swirl
void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN)
2036 ec19c4d1 Blue Swirl
{
2037 c6c7cf05 Blue Swirl
    do_6xx_tlb(env, EPN, 1);
2038 ec19c4d1 Blue Swirl
}
2039 ec19c4d1 Blue Swirl
2040 ec19c4d1 Blue Swirl
/* PowerPC 74xx software TLB load instructions helpers */
2041 c6c7cf05 Blue Swirl
static void do_74xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2042 ec19c4d1 Blue Swirl
{
2043 ec19c4d1 Blue Swirl
    target_ulong RPN, CMP, EPN;
2044 ec19c4d1 Blue Swirl
    int way;
2045 ec19c4d1 Blue Swirl
2046 ec19c4d1 Blue Swirl
    RPN = env->spr[SPR_PTELO];
2047 ec19c4d1 Blue Swirl
    CMP = env->spr[SPR_PTEHI];
2048 ec19c4d1 Blue Swirl
    EPN = env->spr[SPR_TLBMISS] & ~0x3;
2049 ec19c4d1 Blue Swirl
    way = env->spr[SPR_TLBMISS] & 0x3;
2050 ec19c4d1 Blue Swirl
    (void)EPN; /* avoid a compiler warning */
2051 ec19c4d1 Blue Swirl
    LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2052 ec19c4d1 Blue Swirl
              " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2053 ec19c4d1 Blue Swirl
              RPN, way);
2054 ec19c4d1 Blue Swirl
    /* Store this TLB */
2055 ec19c4d1 Blue Swirl
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2056 ec19c4d1 Blue Swirl
                     way, is_code, CMP, RPN);
2057 ec19c4d1 Blue Swirl
}
2058 ec19c4d1 Blue Swirl
2059 c6c7cf05 Blue Swirl
void helper_74xx_tlbd(CPUPPCState *env, target_ulong EPN)
2060 ec19c4d1 Blue Swirl
{
2061 c6c7cf05 Blue Swirl
    do_74xx_tlb(env, EPN, 0);
2062 ec19c4d1 Blue Swirl
}
2063 ec19c4d1 Blue Swirl
2064 c6c7cf05 Blue Swirl
void helper_74xx_tlbi(CPUPPCState *env, target_ulong EPN)
2065 ec19c4d1 Blue Swirl
{
2066 c6c7cf05 Blue Swirl
    do_74xx_tlb(env, EPN, 1);
2067 ec19c4d1 Blue Swirl
}
2068 ec19c4d1 Blue Swirl
2069 ec19c4d1 Blue Swirl
/*****************************************************************************/
2070 ec19c4d1 Blue Swirl
/* PowerPC 601 specific instructions (POWER bridge) */
2071 ec19c4d1 Blue Swirl
2072 c6c7cf05 Blue Swirl
target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
2073 ec19c4d1 Blue Swirl
{
2074 ec19c4d1 Blue Swirl
    mmu_ctx_t ctx;
2075 ec19c4d1 Blue Swirl
    int nb_BATs;
2076 ec19c4d1 Blue Swirl
    target_ulong ret = 0;
2077 ec19c4d1 Blue Swirl
2078 ec19c4d1 Blue Swirl
    /* We don't have to generate many instances of this instruction,
2079 ec19c4d1 Blue Swirl
     * as rac is supervisor only.
2080 ec19c4d1 Blue Swirl
     */
2081 ec19c4d1 Blue Swirl
    /* XXX: FIX THIS: Pretend we have no BAT */
2082 ec19c4d1 Blue Swirl
    nb_BATs = env->nb_BATs;
2083 ec19c4d1 Blue Swirl
    env->nb_BATs = 0;
2084 ec19c4d1 Blue Swirl
    if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) {
2085 ec19c4d1 Blue Swirl
        ret = ctx.raddr;
2086 ec19c4d1 Blue Swirl
    }
2087 ec19c4d1 Blue Swirl
    env->nb_BATs = nb_BATs;
2088 ec19c4d1 Blue Swirl
    return ret;
2089 ec19c4d1 Blue Swirl
}
2090 ec19c4d1 Blue Swirl
2091 ec19c4d1 Blue Swirl
static inline target_ulong booke_tlb_to_page_size(int size)
2092 ec19c4d1 Blue Swirl
{
2093 ec19c4d1 Blue Swirl
    return 1024 << (2 * size);
2094 ec19c4d1 Blue Swirl
}
2095 ec19c4d1 Blue Swirl
2096 ec19c4d1 Blue Swirl
static inline int booke_page_size_to_tlb(target_ulong page_size)
2097 ec19c4d1 Blue Swirl
{
2098 ec19c4d1 Blue Swirl
    int size;
2099 ec19c4d1 Blue Swirl
2100 ec19c4d1 Blue Swirl
    switch (page_size) {
2101 ec19c4d1 Blue Swirl
    case 0x00000400UL:
2102 ec19c4d1 Blue Swirl
        size = 0x0;
2103 ec19c4d1 Blue Swirl
        break;
2104 ec19c4d1 Blue Swirl
    case 0x00001000UL:
2105 ec19c4d1 Blue Swirl
        size = 0x1;
2106 ec19c4d1 Blue Swirl
        break;
2107 ec19c4d1 Blue Swirl
    case 0x00004000UL:
2108 ec19c4d1 Blue Swirl
        size = 0x2;
2109 ec19c4d1 Blue Swirl
        break;
2110 ec19c4d1 Blue Swirl
    case 0x00010000UL:
2111 ec19c4d1 Blue Swirl
        size = 0x3;
2112 ec19c4d1 Blue Swirl
        break;
2113 ec19c4d1 Blue Swirl
    case 0x00040000UL:
2114 ec19c4d1 Blue Swirl
        size = 0x4;
2115 ec19c4d1 Blue Swirl
        break;
2116 ec19c4d1 Blue Swirl
    case 0x00100000UL:
2117 ec19c4d1 Blue Swirl
        size = 0x5;
2118 ec19c4d1 Blue Swirl
        break;
2119 ec19c4d1 Blue Swirl
    case 0x00400000UL:
2120 ec19c4d1 Blue Swirl
        size = 0x6;
2121 ec19c4d1 Blue Swirl
        break;
2122 ec19c4d1 Blue Swirl
    case 0x01000000UL:
2123 ec19c4d1 Blue Swirl
        size = 0x7;
2124 ec19c4d1 Blue Swirl
        break;
2125 ec19c4d1 Blue Swirl
    case 0x04000000UL:
2126 ec19c4d1 Blue Swirl
        size = 0x8;
2127 ec19c4d1 Blue Swirl
        break;
2128 ec19c4d1 Blue Swirl
    case 0x10000000UL:
2129 ec19c4d1 Blue Swirl
        size = 0x9;
2130 ec19c4d1 Blue Swirl
        break;
2131 ec19c4d1 Blue Swirl
    case 0x40000000UL:
2132 ec19c4d1 Blue Swirl
        size = 0xA;
2133 ec19c4d1 Blue Swirl
        break;
2134 ec19c4d1 Blue Swirl
#if defined(TARGET_PPC64)
2135 ec19c4d1 Blue Swirl
    case 0x000100000000ULL:
2136 ec19c4d1 Blue Swirl
        size = 0xB;
2137 ec19c4d1 Blue Swirl
        break;
2138 ec19c4d1 Blue Swirl
    case 0x000400000000ULL:
2139 ec19c4d1 Blue Swirl
        size = 0xC;
2140 ec19c4d1 Blue Swirl
        break;
2141 ec19c4d1 Blue Swirl
    case 0x001000000000ULL:
2142 ec19c4d1 Blue Swirl
        size = 0xD;
2143 ec19c4d1 Blue Swirl
        break;
2144 ec19c4d1 Blue Swirl
    case 0x004000000000ULL:
2145 ec19c4d1 Blue Swirl
        size = 0xE;
2146 ec19c4d1 Blue Swirl
        break;
2147 ec19c4d1 Blue Swirl
    case 0x010000000000ULL:
2148 ec19c4d1 Blue Swirl
        size = 0xF;
2149 ec19c4d1 Blue Swirl
        break;
2150 ec19c4d1 Blue Swirl
#endif
2151 ec19c4d1 Blue Swirl
    default:
2152 ec19c4d1 Blue Swirl
        size = -1;
2153 ec19c4d1 Blue Swirl
        break;
2154 ec19c4d1 Blue Swirl
    }
2155 ec19c4d1 Blue Swirl
2156 ec19c4d1 Blue Swirl
    return size;
2157 ec19c4d1 Blue Swirl
}
2158 ec19c4d1 Blue Swirl
2159 ec19c4d1 Blue Swirl
/* Helpers for 4xx TLB management */
2160 ec19c4d1 Blue Swirl
#define PPC4XX_TLB_ENTRY_MASK       0x0000003f  /* Mask for 64 TLB entries */
2161 ec19c4d1 Blue Swirl
2162 ec19c4d1 Blue Swirl
#define PPC4XX_TLBHI_V              0x00000040
2163 ec19c4d1 Blue Swirl
#define PPC4XX_TLBHI_E              0x00000020
2164 ec19c4d1 Blue Swirl
#define PPC4XX_TLBHI_SIZE_MIN       0
2165 ec19c4d1 Blue Swirl
#define PPC4XX_TLBHI_SIZE_MAX       7
2166 ec19c4d1 Blue Swirl
#define PPC4XX_TLBHI_SIZE_DEFAULT   1
2167 ec19c4d1 Blue Swirl
#define PPC4XX_TLBHI_SIZE_SHIFT     7
2168 ec19c4d1 Blue Swirl
#define PPC4XX_TLBHI_SIZE_MASK      0x00000007
2169 ec19c4d1 Blue Swirl
2170 ec19c4d1 Blue Swirl
#define PPC4XX_TLBLO_EX             0x00000200
2171 ec19c4d1 Blue Swirl
#define PPC4XX_TLBLO_WR             0x00000100
2172 ec19c4d1 Blue Swirl
#define PPC4XX_TLBLO_ATTR_MASK      0x000000FF
2173 ec19c4d1 Blue Swirl
#define PPC4XX_TLBLO_RPN_MASK       0xFFFFFC00
2174 ec19c4d1 Blue Swirl
2175 c6c7cf05 Blue Swirl
target_ulong helper_4xx_tlbre_hi(CPUPPCState *env, target_ulong entry)
2176 ec19c4d1 Blue Swirl
{
2177 ec19c4d1 Blue Swirl
    ppcemb_tlb_t *tlb;
2178 ec19c4d1 Blue Swirl
    target_ulong ret;
2179 ec19c4d1 Blue Swirl
    int size;
2180 ec19c4d1 Blue Swirl
2181 ec19c4d1 Blue Swirl
    entry &= PPC4XX_TLB_ENTRY_MASK;
2182 ec19c4d1 Blue Swirl
    tlb = &env->tlb.tlbe[entry];
2183 ec19c4d1 Blue Swirl
    ret = tlb->EPN;
2184 ec19c4d1 Blue Swirl
    if (tlb->prot & PAGE_VALID) {
2185 ec19c4d1 Blue Swirl
        ret |= PPC4XX_TLBHI_V;
2186 ec19c4d1 Blue Swirl
    }
2187 ec19c4d1 Blue Swirl
    size = booke_page_size_to_tlb(tlb->size);
2188 ec19c4d1 Blue Swirl
    if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) {
2189 ec19c4d1 Blue Swirl
        size = PPC4XX_TLBHI_SIZE_DEFAULT;
2190 ec19c4d1 Blue Swirl
    }
2191 ec19c4d1 Blue Swirl
    ret |= size << PPC4XX_TLBHI_SIZE_SHIFT;
2192 ec19c4d1 Blue Swirl
    env->spr[SPR_40x_PID] = tlb->PID;
2193 ec19c4d1 Blue Swirl
    return ret;
2194 ec19c4d1 Blue Swirl
}
2195 ec19c4d1 Blue Swirl
2196 c6c7cf05 Blue Swirl
target_ulong helper_4xx_tlbre_lo(CPUPPCState *env, target_ulong entry)
2197 ec19c4d1 Blue Swirl
{
2198 ec19c4d1 Blue Swirl
    ppcemb_tlb_t *tlb;
2199 ec19c4d1 Blue Swirl
    target_ulong ret;
2200 ec19c4d1 Blue Swirl
2201 ec19c4d1 Blue Swirl
    entry &= PPC4XX_TLB_ENTRY_MASK;
2202 ec19c4d1 Blue Swirl
    tlb = &env->tlb.tlbe[entry];
2203 ec19c4d1 Blue Swirl
    ret = tlb->RPN;
2204 ec19c4d1 Blue Swirl
    if (tlb->prot & PAGE_EXEC) {
2205 ec19c4d1 Blue Swirl
        ret |= PPC4XX_TLBLO_EX;
2206 ec19c4d1 Blue Swirl
    }
2207 ec19c4d1 Blue Swirl
    if (tlb->prot & PAGE_WRITE) {
2208 ec19c4d1 Blue Swirl
        ret |= PPC4XX_TLBLO_WR;
2209 ec19c4d1 Blue Swirl
    }
2210 ec19c4d1 Blue Swirl
    return ret;
2211 ec19c4d1 Blue Swirl
}
2212 ec19c4d1 Blue Swirl
2213 c6c7cf05 Blue Swirl
void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry,
2214 c6c7cf05 Blue Swirl
                         target_ulong val)
2215 ec19c4d1 Blue Swirl
{
2216 ec19c4d1 Blue Swirl
    ppcemb_tlb_t *tlb;
2217 ec19c4d1 Blue Swirl
    target_ulong page, end;
2218 ec19c4d1 Blue Swirl
2219 ec19c4d1 Blue Swirl
    LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry,
2220 ec19c4d1 Blue Swirl
              val);
2221 ec19c4d1 Blue Swirl
    entry &= PPC4XX_TLB_ENTRY_MASK;
2222 ec19c4d1 Blue Swirl
    tlb = &env->tlb.tlbe[entry];
2223 ec19c4d1 Blue Swirl
    /* Invalidate previous TLB (if it's valid) */
2224 ec19c4d1 Blue Swirl
    if (tlb->prot & PAGE_VALID) {
2225 ec19c4d1 Blue Swirl
        end = tlb->EPN + tlb->size;
2226 ec19c4d1 Blue Swirl
        LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end "
2227 ec19c4d1 Blue Swirl
                  TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2228 ec19c4d1 Blue Swirl
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2229 ec19c4d1 Blue Swirl
            tlb_flush_page(env, page);
2230 ec19c4d1 Blue Swirl
        }
2231 ec19c4d1 Blue Swirl
    }
2232 ec19c4d1 Blue Swirl
    tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT)
2233 ec19c4d1 Blue Swirl
                                       & PPC4XX_TLBHI_SIZE_MASK);
2234 ec19c4d1 Blue Swirl
    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2235 ec19c4d1 Blue Swirl
     * If this ever occurs, one should use the ppcemb target instead
2236 ec19c4d1 Blue Swirl
     * of the ppc or ppc64 one
2237 ec19c4d1 Blue Swirl
     */
2238 ec19c4d1 Blue Swirl
    if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) {
2239 ec19c4d1 Blue Swirl
        cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
2240 ec19c4d1 Blue Swirl
                  "are not supported (%d)\n",
2241 ec19c4d1 Blue Swirl
                  tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
2242 ec19c4d1 Blue Swirl
    }
2243 ec19c4d1 Blue Swirl
    tlb->EPN = val & ~(tlb->size - 1);
2244 ec19c4d1 Blue Swirl
    if (val & PPC4XX_TLBHI_V) {
2245 ec19c4d1 Blue Swirl
        tlb->prot |= PAGE_VALID;
2246 ec19c4d1 Blue Swirl
        if (val & PPC4XX_TLBHI_E) {
2247 ec19c4d1 Blue Swirl
            /* XXX: TO BE FIXED */
2248 ec19c4d1 Blue Swirl
            cpu_abort(env,
2249 ec19c4d1 Blue Swirl
                      "Little-endian TLB entries are not supported by now\n");
2250 ec19c4d1 Blue Swirl
        }
2251 ec19c4d1 Blue Swirl
    } else {
2252 ec19c4d1 Blue Swirl
        tlb->prot &= ~PAGE_VALID;
2253 ec19c4d1 Blue Swirl
    }
2254 ec19c4d1 Blue Swirl
    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2255 ec19c4d1 Blue Swirl
    LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2256 ec19c4d1 Blue Swirl
              " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2257 ec19c4d1 Blue Swirl
              (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2258 ec19c4d1 Blue Swirl
              tlb->prot & PAGE_READ ? 'r' : '-',
2259 ec19c4d1 Blue Swirl
              tlb->prot & PAGE_WRITE ? 'w' : '-',
2260 ec19c4d1 Blue Swirl
              tlb->prot & PAGE_EXEC ? 'x' : '-',
2261 ec19c4d1 Blue Swirl
              tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2262 ec19c4d1 Blue Swirl
    /* Invalidate new TLB (if valid) */
2263 ec19c4d1 Blue Swirl
    if (tlb->prot & PAGE_VALID) {
2264 ec19c4d1 Blue Swirl
        end = tlb->EPN + tlb->size;
2265 ec19c4d1 Blue Swirl
        LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end "
2266 ec19c4d1 Blue Swirl
                  TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2267 ec19c4d1 Blue Swirl
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2268 ec19c4d1 Blue Swirl
            tlb_flush_page(env, page);
2269 ec19c4d1 Blue Swirl
        }
2270 ec19c4d1 Blue Swirl
    }
2271 ec19c4d1 Blue Swirl
}
2272 ec19c4d1 Blue Swirl
2273 c6c7cf05 Blue Swirl
void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry,
2274 c6c7cf05 Blue Swirl
                         target_ulong val)
2275 ec19c4d1 Blue Swirl
{
2276 ec19c4d1 Blue Swirl
    ppcemb_tlb_t *tlb;
2277 ec19c4d1 Blue Swirl
2278 ec19c4d1 Blue Swirl
    LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry,
2279 ec19c4d1 Blue Swirl
              val);
2280 ec19c4d1 Blue Swirl
    entry &= PPC4XX_TLB_ENTRY_MASK;
2281 ec19c4d1 Blue Swirl
    tlb = &env->tlb.tlbe[entry];
2282 ec19c4d1 Blue Swirl
    tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
2283 ec19c4d1 Blue Swirl
    tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
2284 ec19c4d1 Blue Swirl
    tlb->prot = PAGE_READ;
2285 ec19c4d1 Blue Swirl
    if (val & PPC4XX_TLBLO_EX) {
2286 ec19c4d1 Blue Swirl
        tlb->prot |= PAGE_EXEC;
2287 ec19c4d1 Blue Swirl
    }
2288 ec19c4d1 Blue Swirl
    if (val & PPC4XX_TLBLO_WR) {
2289 ec19c4d1 Blue Swirl
        tlb->prot |= PAGE_WRITE;
2290 ec19c4d1 Blue Swirl
    }
2291 ec19c4d1 Blue Swirl
    LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2292 ec19c4d1 Blue Swirl
              " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2293 ec19c4d1 Blue Swirl
              (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2294 ec19c4d1 Blue Swirl
              tlb->prot & PAGE_READ ? 'r' : '-',
2295 ec19c4d1 Blue Swirl
              tlb->prot & PAGE_WRITE ? 'w' : '-',
2296 ec19c4d1 Blue Swirl
              tlb->prot & PAGE_EXEC ? 'x' : '-',
2297 ec19c4d1 Blue Swirl
              tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2298 ec19c4d1 Blue Swirl
}
2299 ec19c4d1 Blue Swirl
2300 c6c7cf05 Blue Swirl
target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address)
2301 ec19c4d1 Blue Swirl
{
2302 ec19c4d1 Blue Swirl
    return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
2303 ec19c4d1 Blue Swirl
}
2304 ec19c4d1 Blue Swirl
2305 ec19c4d1 Blue Swirl
/* PowerPC 440 TLB management */
2306 c6c7cf05 Blue Swirl
void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry,
2307 c6c7cf05 Blue Swirl
                      target_ulong value)
2308 ec19c4d1 Blue Swirl
{
2309 ec19c4d1 Blue Swirl
    ppcemb_tlb_t *tlb;
2310 ec19c4d1 Blue Swirl
    target_ulong EPN, RPN, size;
2311 ec19c4d1 Blue Swirl
    int do_flush_tlbs;
2312 ec19c4d1 Blue Swirl
2313 ec19c4d1 Blue Swirl
    LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx "\n",
2314 ec19c4d1 Blue Swirl
              __func__, word, (int)entry, value);
2315 ec19c4d1 Blue Swirl
    do_flush_tlbs = 0;
2316 ec19c4d1 Blue Swirl
    entry &= 0x3F;
2317 ec19c4d1 Blue Swirl
    tlb = &env->tlb.tlbe[entry];
2318 ec19c4d1 Blue Swirl
    switch (word) {
2319 ec19c4d1 Blue Swirl
    default:
2320 ec19c4d1 Blue Swirl
        /* Just here to please gcc */
2321 ec19c4d1 Blue Swirl
    case 0:
2322 ec19c4d1 Blue Swirl
        EPN = value & 0xFFFFFC00;
2323 ec19c4d1 Blue Swirl
        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) {
2324 ec19c4d1 Blue Swirl
            do_flush_tlbs = 1;
2325 ec19c4d1 Blue Swirl
        }
2326 ec19c4d1 Blue Swirl
        tlb->EPN = EPN;
2327 ec19c4d1 Blue Swirl
        size = booke_tlb_to_page_size((value >> 4) & 0xF);
2328 ec19c4d1 Blue Swirl
        if ((tlb->prot & PAGE_VALID) && tlb->size < size) {
2329 ec19c4d1 Blue Swirl
            do_flush_tlbs = 1;
2330 ec19c4d1 Blue Swirl
        }
2331 ec19c4d1 Blue Swirl
        tlb->size = size;
2332 ec19c4d1 Blue Swirl
        tlb->attr &= ~0x1;
2333 ec19c4d1 Blue Swirl
        tlb->attr |= (value >> 8) & 1;
2334 ec19c4d1 Blue Swirl
        if (value & 0x200) {
2335 ec19c4d1 Blue Swirl
            tlb->prot |= PAGE_VALID;
2336 ec19c4d1 Blue Swirl
        } else {
2337 ec19c4d1 Blue Swirl
            if (tlb->prot & PAGE_VALID) {
2338 ec19c4d1 Blue Swirl
                tlb->prot &= ~PAGE_VALID;
2339 ec19c4d1 Blue Swirl
                do_flush_tlbs = 1;
2340 ec19c4d1 Blue Swirl
            }
2341 ec19c4d1 Blue Swirl
        }
2342 ec19c4d1 Blue Swirl
        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
2343 ec19c4d1 Blue Swirl
        if (do_flush_tlbs) {
2344 ec19c4d1 Blue Swirl
            tlb_flush(env, 1);
2345 ec19c4d1 Blue Swirl
        }
2346 ec19c4d1 Blue Swirl
        break;
2347 ec19c4d1 Blue Swirl
    case 1:
2348 ec19c4d1 Blue Swirl
        RPN = value & 0xFFFFFC0F;
2349 ec19c4d1 Blue Swirl
        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) {
2350 ec19c4d1 Blue Swirl
            tlb_flush(env, 1);
2351 ec19c4d1 Blue Swirl
        }
2352 ec19c4d1 Blue Swirl
        tlb->RPN = RPN;
2353 ec19c4d1 Blue Swirl
        break;
2354 ec19c4d1 Blue Swirl
    case 2:
2355 ec19c4d1 Blue Swirl
        tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
2356 ec19c4d1 Blue Swirl
        tlb->prot = tlb->prot & PAGE_VALID;
2357 ec19c4d1 Blue Swirl
        if (value & 0x1) {
2358 ec19c4d1 Blue Swirl
            tlb->prot |= PAGE_READ << 4;
2359 ec19c4d1 Blue Swirl
        }
2360 ec19c4d1 Blue Swirl
        if (value & 0x2) {
2361 ec19c4d1 Blue Swirl
            tlb->prot |= PAGE_WRITE << 4;
2362 ec19c4d1 Blue Swirl
        }
2363 ec19c4d1 Blue Swirl
        if (value & 0x4) {
2364 ec19c4d1 Blue Swirl
            tlb->prot |= PAGE_EXEC << 4;
2365 ec19c4d1 Blue Swirl
        }
2366 ec19c4d1 Blue Swirl
        if (value & 0x8) {
2367 ec19c4d1 Blue Swirl
            tlb->prot |= PAGE_READ;
2368 ec19c4d1 Blue Swirl
        }
2369 ec19c4d1 Blue Swirl
        if (value & 0x10) {
2370 ec19c4d1 Blue Swirl
            tlb->prot |= PAGE_WRITE;
2371 ec19c4d1 Blue Swirl
        }
2372 ec19c4d1 Blue Swirl
        if (value & 0x20) {
2373 ec19c4d1 Blue Swirl
            tlb->prot |= PAGE_EXEC;
2374 ec19c4d1 Blue Swirl
        }
2375 ec19c4d1 Blue Swirl
        break;
2376 ec19c4d1 Blue Swirl
    }
2377 ec19c4d1 Blue Swirl
}
2378 ec19c4d1 Blue Swirl
2379 c6c7cf05 Blue Swirl
target_ulong helper_440_tlbre(CPUPPCState *env, uint32_t word,
2380 c6c7cf05 Blue Swirl
                              target_ulong entry)
2381 ec19c4d1 Blue Swirl
{
2382 ec19c4d1 Blue Swirl
    ppcemb_tlb_t *tlb;
2383 ec19c4d1 Blue Swirl
    target_ulong ret;
2384 ec19c4d1 Blue Swirl
    int size;
2385 ec19c4d1 Blue Swirl
2386 ec19c4d1 Blue Swirl
    entry &= 0x3F;
2387 ec19c4d1 Blue Swirl
    tlb = &env->tlb.tlbe[entry];
2388 ec19c4d1 Blue Swirl
    switch (word) {
2389 ec19c4d1 Blue Swirl
    default:
2390 ec19c4d1 Blue Swirl
        /* Just here to please gcc */
2391 ec19c4d1 Blue Swirl
    case 0:
2392 ec19c4d1 Blue Swirl
        ret = tlb->EPN;
2393 ec19c4d1 Blue Swirl
        size = booke_page_size_to_tlb(tlb->size);
2394 ec19c4d1 Blue Swirl
        if (size < 0 || size > 0xF) {
2395 ec19c4d1 Blue Swirl
            size = 1;
2396 ec19c4d1 Blue Swirl
        }
2397 ec19c4d1 Blue Swirl
        ret |= size << 4;
2398 ec19c4d1 Blue Swirl
        if (tlb->attr & 0x1) {
2399 ec19c4d1 Blue Swirl
            ret |= 0x100;
2400 ec19c4d1 Blue Swirl
        }
2401 ec19c4d1 Blue Swirl
        if (tlb->prot & PAGE_VALID) {
2402 ec19c4d1 Blue Swirl
            ret |= 0x200;
2403 ec19c4d1 Blue Swirl
        }
2404 ec19c4d1 Blue Swirl
        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2405 ec19c4d1 Blue Swirl
        env->spr[SPR_440_MMUCR] |= tlb->PID;
2406 ec19c4d1 Blue Swirl
        break;
2407 ec19c4d1 Blue Swirl
    case 1:
2408 ec19c4d1 Blue Swirl
        ret = tlb->RPN;
2409 ec19c4d1 Blue Swirl
        break;
2410 ec19c4d1 Blue Swirl
    case 2:
2411 ec19c4d1 Blue Swirl
        ret = tlb->attr & ~0x1;
2412 ec19c4d1 Blue Swirl
        if (tlb->prot & (PAGE_READ << 4)) {
2413 ec19c4d1 Blue Swirl
            ret |= 0x1;
2414 ec19c4d1 Blue Swirl
        }
2415 ec19c4d1 Blue Swirl
        if (tlb->prot & (PAGE_WRITE << 4)) {
2416 ec19c4d1 Blue Swirl
            ret |= 0x2;
2417 ec19c4d1 Blue Swirl
        }
2418 ec19c4d1 Blue Swirl
        if (tlb->prot & (PAGE_EXEC << 4)) {
2419 ec19c4d1 Blue Swirl
            ret |= 0x4;
2420 ec19c4d1 Blue Swirl
        }
2421 ec19c4d1 Blue Swirl
        if (tlb->prot & PAGE_READ) {
2422 ec19c4d1 Blue Swirl
            ret |= 0x8;
2423 ec19c4d1 Blue Swirl
        }
2424 ec19c4d1 Blue Swirl
        if (tlb->prot & PAGE_WRITE) {
2425 ec19c4d1 Blue Swirl
            ret |= 0x10;
2426 ec19c4d1 Blue Swirl
        }
2427 ec19c4d1 Blue Swirl
        if (tlb->prot & PAGE_EXEC) {
2428 ec19c4d1 Blue Swirl
            ret |= 0x20;
2429 ec19c4d1 Blue Swirl
        }
2430 ec19c4d1 Blue Swirl
        break;
2431 ec19c4d1 Blue Swirl
    }
2432 ec19c4d1 Blue Swirl
    return ret;
2433 ec19c4d1 Blue Swirl
}
2434 ec19c4d1 Blue Swirl
2435 c6c7cf05 Blue Swirl
target_ulong helper_440_tlbsx(CPUPPCState *env, target_ulong address)
2436 ec19c4d1 Blue Swirl
{
2437 ec19c4d1 Blue Swirl
    return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
2438 ec19c4d1 Blue Swirl
}
2439 ec19c4d1 Blue Swirl
2440 ec19c4d1 Blue Swirl
/* PowerPC BookE 2.06 TLB management */
2441 ec19c4d1 Blue Swirl
2442 ec19c4d1 Blue Swirl
static ppcmas_tlb_t *booke206_cur_tlb(CPUPPCState *env)
2443 ec19c4d1 Blue Swirl
{
2444 ec19c4d1 Blue Swirl
    uint32_t tlbncfg = 0;
2445 ec19c4d1 Blue Swirl
    int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
2446 ec19c4d1 Blue Swirl
    int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
2447 ec19c4d1 Blue Swirl
    int tlb;
2448 ec19c4d1 Blue Swirl
2449 ec19c4d1 Blue Swirl
    tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2450 ec19c4d1 Blue Swirl
    tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb];
2451 ec19c4d1 Blue Swirl
2452 ec19c4d1 Blue Swirl
    if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) {
2453 ec19c4d1 Blue Swirl
        cpu_abort(env, "we don't support HES yet\n");
2454 ec19c4d1 Blue Swirl
    }
2455 ec19c4d1 Blue Swirl
2456 ec19c4d1 Blue Swirl
    return booke206_get_tlbm(env, tlb, ea, esel);
2457 ec19c4d1 Blue Swirl
}
2458 ec19c4d1 Blue Swirl
2459 c6c7cf05 Blue Swirl
void helper_booke_setpid(CPUPPCState *env, uint32_t pidn, target_ulong pid)
2460 ec19c4d1 Blue Swirl
{
2461 ec19c4d1 Blue Swirl
    env->spr[pidn] = pid;
2462 ec19c4d1 Blue Swirl
    /* changing PIDs mean we're in a different address space now */
2463 ec19c4d1 Blue Swirl
    tlb_flush(env, 1);
2464 ec19c4d1 Blue Swirl
}
2465 ec19c4d1 Blue Swirl
2466 c6c7cf05 Blue Swirl
void helper_booke206_tlbwe(CPUPPCState *env)
2467 ec19c4d1 Blue Swirl
{
2468 ec19c4d1 Blue Swirl
    uint32_t tlbncfg, tlbn;
2469 ec19c4d1 Blue Swirl
    ppcmas_tlb_t *tlb;
2470 ec19c4d1 Blue Swirl
    uint32_t size_tlb, size_ps;
2471 77c2cf33 Fabien Chouteau
    target_ulong mask;
2472 77c2cf33 Fabien Chouteau
2473 ec19c4d1 Blue Swirl
2474 ec19c4d1 Blue Swirl
    switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
2475 ec19c4d1 Blue Swirl
    case MAS0_WQ_ALWAYS:
2476 ec19c4d1 Blue Swirl
        /* good to go, write that entry */
2477 ec19c4d1 Blue Swirl
        break;
2478 ec19c4d1 Blue Swirl
    case MAS0_WQ_COND:
2479 ec19c4d1 Blue Swirl
        /* XXX check if reserved */
2480 ec19c4d1 Blue Swirl
        if (0) {
2481 ec19c4d1 Blue Swirl
            return;
2482 ec19c4d1 Blue Swirl
        }
2483 ec19c4d1 Blue Swirl
        break;
2484 ec19c4d1 Blue Swirl
    case MAS0_WQ_CLR_RSRV:
2485 ec19c4d1 Blue Swirl
        /* XXX clear entry */
2486 ec19c4d1 Blue Swirl
        return;
2487 ec19c4d1 Blue Swirl
    default:
2488 ec19c4d1 Blue Swirl
        /* no idea what to do */
2489 ec19c4d1 Blue Swirl
        return;
2490 ec19c4d1 Blue Swirl
    }
2491 ec19c4d1 Blue Swirl
2492 ec19c4d1 Blue Swirl
    if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) &&
2493 ec19c4d1 Blue Swirl
        !msr_gs) {
2494 ec19c4d1 Blue Swirl
        /* XXX we don't support direct LRAT setting yet */
2495 ec19c4d1 Blue Swirl
        fprintf(stderr, "cpu: don't support LRAT setting yet\n");
2496 ec19c4d1 Blue Swirl
        return;
2497 ec19c4d1 Blue Swirl
    }
2498 ec19c4d1 Blue Swirl
2499 ec19c4d1 Blue Swirl
    tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2500 ec19c4d1 Blue Swirl
    tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
2501 ec19c4d1 Blue Swirl
2502 ec19c4d1 Blue Swirl
    tlb = booke206_cur_tlb(env);
2503 ec19c4d1 Blue Swirl
2504 ec19c4d1 Blue Swirl
    if (!tlb) {
2505 ec19c4d1 Blue Swirl
        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
2506 ec19c4d1 Blue Swirl
                                   POWERPC_EXCP_INVAL |
2507 ec19c4d1 Blue Swirl
                                   POWERPC_EXCP_INVAL_INVAL);
2508 ec19c4d1 Blue Swirl
    }
2509 ec19c4d1 Blue Swirl
2510 ec19c4d1 Blue Swirl
    /* check that we support the targeted size */
2511 ec19c4d1 Blue Swirl
    size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
2512 ec19c4d1 Blue Swirl
    size_ps = booke206_tlbnps(env, tlbn);
2513 ec19c4d1 Blue Swirl
    if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) &&
2514 ec19c4d1 Blue Swirl
        !(size_ps & (1 << size_tlb))) {
2515 ec19c4d1 Blue Swirl
        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
2516 ec19c4d1 Blue Swirl
                                   POWERPC_EXCP_INVAL |
2517 ec19c4d1 Blue Swirl
                                   POWERPC_EXCP_INVAL_INVAL);
2518 ec19c4d1 Blue Swirl
    }
2519 ec19c4d1 Blue Swirl
2520 ec19c4d1 Blue Swirl
    if (msr_gs) {
2521 ec19c4d1 Blue Swirl
        cpu_abort(env, "missing HV implementation\n");
2522 ec19c4d1 Blue Swirl
    }
2523 ec19c4d1 Blue Swirl
    tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
2524 ec19c4d1 Blue Swirl
        env->spr[SPR_BOOKE_MAS3];
2525 ec19c4d1 Blue Swirl
    tlb->mas1 = env->spr[SPR_BOOKE_MAS1];
2526 ec19c4d1 Blue Swirl
2527 ec19c4d1 Blue Swirl
    /* MAV 1.0 only */
2528 ec19c4d1 Blue Swirl
    if (!(tlbncfg & TLBnCFG_AVAIL)) {
2529 ec19c4d1 Blue Swirl
        /* force !AVAIL TLB entries to correct page size */
2530 ec19c4d1 Blue Swirl
        tlb->mas1 &= ~MAS1_TSIZE_MASK;
2531 ec19c4d1 Blue Swirl
        /* XXX can be configured in MMUCSR0 */
2532 ec19c4d1 Blue Swirl
        tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12;
2533 ec19c4d1 Blue Swirl
    }
2534 ec19c4d1 Blue Swirl
2535 77c2cf33 Fabien Chouteau
    /* Make a mask from TLB size to discard invalid bits in EPN field */
2536 77c2cf33 Fabien Chouteau
    mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2537 77c2cf33 Fabien Chouteau
    /* Add a mask for page attributes */
2538 77c2cf33 Fabien Chouteau
    mask |= MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E;
2539 77c2cf33 Fabien Chouteau
2540 77c2cf33 Fabien Chouteau
    if (!msr_cm) {
2541 77c2cf33 Fabien Chouteau
        /* Executing a tlbwe instruction in 32-bit mode will set
2542 77c2cf33 Fabien Chouteau
         * bits 0:31 of the TLB EPN field to zero.
2543 77c2cf33 Fabien Chouteau
         */
2544 77c2cf33 Fabien Chouteau
        mask &= 0xffffffff;
2545 77c2cf33 Fabien Chouteau
    }
2546 77c2cf33 Fabien Chouteau
2547 77c2cf33 Fabien Chouteau
    tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & mask;
2548 ec19c4d1 Blue Swirl
2549 ec19c4d1 Blue Swirl
    if (!(tlbncfg & TLBnCFG_IPROT)) {
2550 ec19c4d1 Blue Swirl
        /* no IPROT supported by TLB */
2551 ec19c4d1 Blue Swirl
        tlb->mas1 &= ~MAS1_IPROT;
2552 ec19c4d1 Blue Swirl
    }
2553 ec19c4d1 Blue Swirl
2554 ec19c4d1 Blue Swirl
    if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) {
2555 ec19c4d1 Blue Swirl
        tlb_flush_page(env, tlb->mas2 & MAS2_EPN_MASK);
2556 ec19c4d1 Blue Swirl
    } else {
2557 ec19c4d1 Blue Swirl
        tlb_flush(env, 1);
2558 ec19c4d1 Blue Swirl
    }
2559 ec19c4d1 Blue Swirl
}
2560 ec19c4d1 Blue Swirl
2561 ec19c4d1 Blue Swirl
static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb)
2562 ec19c4d1 Blue Swirl
{
2563 ec19c4d1 Blue Swirl
    int tlbn = booke206_tlbm_to_tlbn(env, tlb);
2564 ec19c4d1 Blue Swirl
    int way = booke206_tlbm_to_way(env, tlb);
2565 ec19c4d1 Blue Swirl
2566 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT;
2567 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT;
2568 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2569 ec19c4d1 Blue Swirl
2570 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS1] = tlb->mas1;
2571 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS2] = tlb->mas2;
2572 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3;
2573 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32;
2574 ec19c4d1 Blue Swirl
}
2575 ec19c4d1 Blue Swirl
2576 c6c7cf05 Blue Swirl
void helper_booke206_tlbre(CPUPPCState *env)
2577 ec19c4d1 Blue Swirl
{
2578 ec19c4d1 Blue Swirl
    ppcmas_tlb_t *tlb = NULL;
2579 ec19c4d1 Blue Swirl
2580 ec19c4d1 Blue Swirl
    tlb = booke206_cur_tlb(env);
2581 ec19c4d1 Blue Swirl
    if (!tlb) {
2582 ec19c4d1 Blue Swirl
        env->spr[SPR_BOOKE_MAS1] = 0;
2583 ec19c4d1 Blue Swirl
    } else {
2584 ec19c4d1 Blue Swirl
        booke206_tlb_to_mas(env, tlb);
2585 ec19c4d1 Blue Swirl
    }
2586 ec19c4d1 Blue Swirl
}
2587 ec19c4d1 Blue Swirl
2588 c6c7cf05 Blue Swirl
void helper_booke206_tlbsx(CPUPPCState *env, target_ulong address)
2589 ec19c4d1 Blue Swirl
{
2590 ec19c4d1 Blue Swirl
    ppcmas_tlb_t *tlb = NULL;
2591 ec19c4d1 Blue Swirl
    int i, j;
2592 a8170e5e Avi Kivity
    hwaddr raddr;
2593 ec19c4d1 Blue Swirl
    uint32_t spid, sas;
2594 ec19c4d1 Blue Swirl
2595 ec19c4d1 Blue Swirl
    spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT;
2596 ec19c4d1 Blue Swirl
    sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS;
2597 ec19c4d1 Blue Swirl
2598 ec19c4d1 Blue Swirl
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2599 ec19c4d1 Blue Swirl
        int ways = booke206_tlb_ways(env, i);
2600 ec19c4d1 Blue Swirl
2601 ec19c4d1 Blue Swirl
        for (j = 0; j < ways; j++) {
2602 ec19c4d1 Blue Swirl
            tlb = booke206_get_tlbm(env, i, address, j);
2603 ec19c4d1 Blue Swirl
2604 ec19c4d1 Blue Swirl
            if (!tlb) {
2605 ec19c4d1 Blue Swirl
                continue;
2606 ec19c4d1 Blue Swirl
            }
2607 ec19c4d1 Blue Swirl
2608 ec19c4d1 Blue Swirl
            if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
2609 ec19c4d1 Blue Swirl
                continue;
2610 ec19c4d1 Blue Swirl
            }
2611 ec19c4d1 Blue Swirl
2612 ec19c4d1 Blue Swirl
            if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
2613 ec19c4d1 Blue Swirl
                continue;
2614 ec19c4d1 Blue Swirl
            }
2615 ec19c4d1 Blue Swirl
2616 ec19c4d1 Blue Swirl
            booke206_tlb_to_mas(env, tlb);
2617 ec19c4d1 Blue Swirl
            return;
2618 ec19c4d1 Blue Swirl
        }
2619 ec19c4d1 Blue Swirl
    }
2620 ec19c4d1 Blue Swirl
2621 ec19c4d1 Blue Swirl
    /* no entry found, fill with defaults */
2622 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
2623 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
2624 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
2625 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS3] = 0;
2626 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS7] = 0;
2627 ec19c4d1 Blue Swirl
2628 ec19c4d1 Blue Swirl
    if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) {
2629 ec19c4d1 Blue Swirl
        env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
2630 ec19c4d1 Blue Swirl
    }
2631 ec19c4d1 Blue Swirl
2632 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16)
2633 ec19c4d1 Blue Swirl
        << MAS1_TID_SHIFT;
2634 ec19c4d1 Blue Swirl
2635 ec19c4d1 Blue Swirl
    /* next victim logic */
2636 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
2637 ec19c4d1 Blue Swirl
    env->last_way++;
2638 ec19c4d1 Blue Swirl
    env->last_way &= booke206_tlb_ways(env, 0) - 1;
2639 ec19c4d1 Blue Swirl
    env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2640 ec19c4d1 Blue Swirl
}
2641 ec19c4d1 Blue Swirl
2642 ec19c4d1 Blue Swirl
static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn,
2643 ec19c4d1 Blue Swirl
                                              uint32_t ea)
2644 ec19c4d1 Blue Swirl
{
2645 ec19c4d1 Blue Swirl
    int i;
2646 ec19c4d1 Blue Swirl
    int ways = booke206_tlb_ways(env, tlbn);
2647 ec19c4d1 Blue Swirl
    target_ulong mask;
2648 ec19c4d1 Blue Swirl
2649 ec19c4d1 Blue Swirl
    for (i = 0; i < ways; i++) {
2650 ec19c4d1 Blue Swirl
        ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
2651 ec19c4d1 Blue Swirl
        if (!tlb) {
2652 ec19c4d1 Blue Swirl
            continue;
2653 ec19c4d1 Blue Swirl
        }
2654 ec19c4d1 Blue Swirl
        mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2655 ec19c4d1 Blue Swirl
        if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
2656 ec19c4d1 Blue Swirl
            !(tlb->mas1 & MAS1_IPROT)) {
2657 ec19c4d1 Blue Swirl
            tlb->mas1 &= ~MAS1_VALID;
2658 ec19c4d1 Blue Swirl
        }
2659 ec19c4d1 Blue Swirl
    }
2660 ec19c4d1 Blue Swirl
}
2661 ec19c4d1 Blue Swirl
2662 c6c7cf05 Blue Swirl
void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address)
2663 ec19c4d1 Blue Swirl
{
2664 ec19c4d1 Blue Swirl
    if (address & 0x4) {
2665 ec19c4d1 Blue Swirl
        /* flush all entries */
2666 ec19c4d1 Blue Swirl
        if (address & 0x8) {
2667 ec19c4d1 Blue Swirl
            /* flush all of TLB1 */
2668 ec19c4d1 Blue Swirl
            booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1);
2669 ec19c4d1 Blue Swirl
        } else {
2670 ec19c4d1 Blue Swirl
            /* flush all of TLB0 */
2671 ec19c4d1 Blue Swirl
            booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0);
2672 ec19c4d1 Blue Swirl
        }
2673 ec19c4d1 Blue Swirl
        return;
2674 ec19c4d1 Blue Swirl
    }
2675 ec19c4d1 Blue Swirl
2676 ec19c4d1 Blue Swirl
    if (address & 0x8) {
2677 ec19c4d1 Blue Swirl
        /* flush TLB1 entries */
2678 ec19c4d1 Blue Swirl
        booke206_invalidate_ea_tlb(env, 1, address);
2679 ec19c4d1 Blue Swirl
        tlb_flush(env, 1);
2680 ec19c4d1 Blue Swirl
    } else {
2681 ec19c4d1 Blue Swirl
        /* flush TLB0 entries */
2682 ec19c4d1 Blue Swirl
        booke206_invalidate_ea_tlb(env, 0, address);
2683 ec19c4d1 Blue Swirl
        tlb_flush_page(env, address & MAS2_EPN_MASK);
2684 ec19c4d1 Blue Swirl
    }
2685 ec19c4d1 Blue Swirl
}
2686 ec19c4d1 Blue Swirl
2687 c6c7cf05 Blue Swirl
void helper_booke206_tlbilx0(CPUPPCState *env, target_ulong address)
2688 ec19c4d1 Blue Swirl
{
2689 ec19c4d1 Blue Swirl
    /* XXX missing LPID handling */
2690 ec19c4d1 Blue Swirl
    booke206_flush_tlb(env, -1, 1);
2691 ec19c4d1 Blue Swirl
}
2692 ec19c4d1 Blue Swirl
2693 c6c7cf05 Blue Swirl
void helper_booke206_tlbilx1(CPUPPCState *env, target_ulong address)
2694 ec19c4d1 Blue Swirl
{
2695 ec19c4d1 Blue Swirl
    int i, j;
2696 ec19c4d1 Blue Swirl
    int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2697 ec19c4d1 Blue Swirl
    ppcmas_tlb_t *tlb = env->tlb.tlbm;
2698 ec19c4d1 Blue Swirl
    int tlb_size;
2699 ec19c4d1 Blue Swirl
2700 ec19c4d1 Blue Swirl
    /* XXX missing LPID handling */
2701 ec19c4d1 Blue Swirl
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2702 ec19c4d1 Blue Swirl
        tlb_size = booke206_tlb_size(env, i);
2703 ec19c4d1 Blue Swirl
        for (j = 0; j < tlb_size; j++) {
2704 ec19c4d1 Blue Swirl
            if (!(tlb[j].mas1 & MAS1_IPROT) &&
2705 ec19c4d1 Blue Swirl
                ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) {
2706 ec19c4d1 Blue Swirl
                tlb[j].mas1 &= ~MAS1_VALID;
2707 ec19c4d1 Blue Swirl
            }
2708 ec19c4d1 Blue Swirl
        }
2709 ec19c4d1 Blue Swirl
        tlb += booke206_tlb_size(env, i);
2710 ec19c4d1 Blue Swirl
    }
2711 ec19c4d1 Blue Swirl
    tlb_flush(env, 1);
2712 ec19c4d1 Blue Swirl
}
2713 ec19c4d1 Blue Swirl
2714 c6c7cf05 Blue Swirl
void helper_booke206_tlbilx3(CPUPPCState *env, target_ulong address)
2715 ec19c4d1 Blue Swirl
{
2716 ec19c4d1 Blue Swirl
    int i, j;
2717 ec19c4d1 Blue Swirl
    ppcmas_tlb_t *tlb;
2718 ec19c4d1 Blue Swirl
    int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2719 ec19c4d1 Blue Swirl
    int pid = tid >> MAS6_SPID_SHIFT;
2720 ec19c4d1 Blue Swirl
    int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS;
2721 ec19c4d1 Blue Swirl
    int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0;
2722 ec19c4d1 Blue Swirl
    /* XXX check for unsupported isize and raise an invalid opcode then */
2723 ec19c4d1 Blue Swirl
    int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK;
2724 ec19c4d1 Blue Swirl
    /* XXX implement MAV2 handling */
2725 ec19c4d1 Blue Swirl
    bool mav2 = false;
2726 ec19c4d1 Blue Swirl
2727 ec19c4d1 Blue Swirl
    /* XXX missing LPID handling */
2728 ec19c4d1 Blue Swirl
    /* flush by pid and ea */
2729 ec19c4d1 Blue Swirl
    for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2730 ec19c4d1 Blue Swirl
        int ways = booke206_tlb_ways(env, i);
2731 ec19c4d1 Blue Swirl
2732 ec19c4d1 Blue Swirl
        for (j = 0; j < ways; j++) {
2733 ec19c4d1 Blue Swirl
            tlb = booke206_get_tlbm(env, i, address, j);
2734 ec19c4d1 Blue Swirl
            if (!tlb) {
2735 ec19c4d1 Blue Swirl
                continue;
2736 ec19c4d1 Blue Swirl
            }
2737 ec19c4d1 Blue Swirl
            if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
2738 ec19c4d1 Blue Swirl
                (tlb->mas1 & MAS1_IPROT) ||
2739 ec19c4d1 Blue Swirl
                ((tlb->mas1 & MAS1_IND) != ind) ||
2740 ec19c4d1 Blue Swirl
                ((tlb->mas8 & MAS8_TGS) != sgs)) {
2741 ec19c4d1 Blue Swirl
                continue;
2742 ec19c4d1 Blue Swirl
            }
2743 ec19c4d1 Blue Swirl
            if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) {
2744 ec19c4d1 Blue Swirl
                /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2745 ec19c4d1 Blue Swirl
                continue;
2746 ec19c4d1 Blue Swirl
            }
2747 ec19c4d1 Blue Swirl
            /* XXX e500mc doesn't match SAS, but other cores might */
2748 ec19c4d1 Blue Swirl
            tlb->mas1 &= ~MAS1_VALID;
2749 ec19c4d1 Blue Swirl
        }
2750 ec19c4d1 Blue Swirl
    }
2751 ec19c4d1 Blue Swirl
    tlb_flush(env, 1);
2752 ec19c4d1 Blue Swirl
}
2753 ec19c4d1 Blue Swirl
2754 c6c7cf05 Blue Swirl
void helper_booke206_tlbflush(CPUPPCState *env, uint32_t type)
2755 ec19c4d1 Blue Swirl
{
2756 ec19c4d1 Blue Swirl
    int flags = 0;
2757 ec19c4d1 Blue Swirl
2758 ec19c4d1 Blue Swirl
    if (type & 2) {
2759 ec19c4d1 Blue Swirl
        flags |= BOOKE206_FLUSH_TLB1;
2760 ec19c4d1 Blue Swirl
    }
2761 ec19c4d1 Blue Swirl
2762 ec19c4d1 Blue Swirl
    if (type & 4) {
2763 ec19c4d1 Blue Swirl
        flags |= BOOKE206_FLUSH_TLB0;
2764 ec19c4d1 Blue Swirl
    }
2765 ec19c4d1 Blue Swirl
2766 ec19c4d1 Blue Swirl
    booke206_flush_tlb(env, flags, 1);
2767 ec19c4d1 Blue Swirl
}
2768 eb20c1c6 David Gibson
2769 eb20c1c6 David Gibson
2770 eb20c1c6 David Gibson
/*****************************************************************************/
2771 eb20c1c6 David Gibson
2772 eb20c1c6 David Gibson
#define MMUSUFFIX _mmu
2773 eb20c1c6 David Gibson
2774 eb20c1c6 David Gibson
#define SHIFT 0
2775 eb20c1c6 David Gibson
#include "exec/softmmu_template.h"
2776 eb20c1c6 David Gibson
2777 eb20c1c6 David Gibson
#define SHIFT 1
2778 eb20c1c6 David Gibson
#include "exec/softmmu_template.h"
2779 eb20c1c6 David Gibson
2780 eb20c1c6 David Gibson
#define SHIFT 2
2781 eb20c1c6 David Gibson
#include "exec/softmmu_template.h"
2782 eb20c1c6 David Gibson
2783 eb20c1c6 David Gibson
#define SHIFT 3
2784 eb20c1c6 David Gibson
#include "exec/softmmu_template.h"
2785 eb20c1c6 David Gibson
2786 eb20c1c6 David Gibson
/* try to fill the TLB and return an exception if error. If retaddr is
2787 eb20c1c6 David Gibson
   NULL, it means that the function was called in C code (i.e. not
2788 eb20c1c6 David Gibson
   from generated code or from helper.c) */
2789 eb20c1c6 David Gibson
/* XXX: fix it to restore all registers */
2790 eb20c1c6 David Gibson
void tlb_fill(CPUPPCState *env, target_ulong addr, int is_write, int mmu_idx,
2791 eb20c1c6 David Gibson
              uintptr_t retaddr)
2792 eb20c1c6 David Gibson
{
2793 b632a148 David Gibson
    CPUState *cpu = ENV_GET_CPU(env);
2794 b632a148 David Gibson
    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
2795 eb20c1c6 David Gibson
    int ret;
2796 eb20c1c6 David Gibson
2797 b632a148 David Gibson
    if (pcc->handle_mmu_fault) {
2798 b632a148 David Gibson
        ret = pcc->handle_mmu_fault(env, addr, is_write, mmu_idx);
2799 b632a148 David Gibson
    } else {
2800 b632a148 David Gibson
        ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx);
2801 b632a148 David Gibson
    }
2802 eb20c1c6 David Gibson
    if (unlikely(ret != 0)) {
2803 eb20c1c6 David Gibson
        if (likely(retaddr)) {
2804 eb20c1c6 David Gibson
            /* now we have a real cpu fault */
2805 eb20c1c6 David Gibson
            cpu_restore_state(env, retaddr);
2806 eb20c1c6 David Gibson
        }
2807 eb20c1c6 David Gibson
        helper_raise_exception_err(env, env->exception_index, env->error_code);
2808 eb20c1c6 David Gibson
    }
2809 eb20c1c6 David Gibson
}