Statistics
| Branch: | Revision:

root / target-sparc / mmu_helper.c @ b072a3c8

History | View | Annotate | Download (27 kB)

1 163fa5ca Blue Swirl
/*
2 163fa5ca Blue Swirl
 *  Sparc MMU helpers
3 163fa5ca Blue Swirl
 *
4 163fa5ca Blue Swirl
 *  Copyright (c) 2003-2005 Fabrice Bellard
5 163fa5ca Blue Swirl
 *
6 163fa5ca Blue Swirl
 * This library is free software; you can redistribute it and/or
7 163fa5ca Blue Swirl
 * modify it under the terms of the GNU Lesser General Public
8 163fa5ca Blue Swirl
 * License as published by the Free Software Foundation; either
9 163fa5ca Blue Swirl
 * version 2 of the License, or (at your option) any later version.
10 163fa5ca Blue Swirl
 *
11 163fa5ca Blue Swirl
 * This library is distributed in the hope that it will be useful,
12 163fa5ca Blue Swirl
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 163fa5ca Blue Swirl
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 163fa5ca Blue Swirl
 * Lesser General Public License for more details.
15 163fa5ca Blue Swirl
 *
16 163fa5ca Blue Swirl
 * You should have received a copy of the GNU Lesser General Public
17 163fa5ca Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 163fa5ca Blue Swirl
 */
19 163fa5ca Blue Swirl
20 163fa5ca Blue Swirl
#include "cpu.h"
21 ec0ceb17 Blue Swirl
#include "trace.h"
22 cc4aa830 Avi Kivity
#include "exec-memory.h"
23 163fa5ca Blue Swirl
24 163fa5ca Blue Swirl
/* Sparc MMU emulation */
25 163fa5ca Blue Swirl
26 163fa5ca Blue Swirl
#if defined(CONFIG_USER_ONLY)
27 163fa5ca Blue Swirl
28 163fa5ca Blue Swirl
int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
29 163fa5ca Blue Swirl
                               int mmu_idx)
30 163fa5ca Blue Swirl
{
31 163fa5ca Blue Swirl
    if (rw & 2) {
32 163fa5ca Blue Swirl
        env1->exception_index = TT_TFAULT;
33 163fa5ca Blue Swirl
    } else {
34 163fa5ca Blue Swirl
        env1->exception_index = TT_DFAULT;
35 163fa5ca Blue Swirl
    }
36 163fa5ca Blue Swirl
    return 1;
37 163fa5ca Blue Swirl
}
38 163fa5ca Blue Swirl
39 163fa5ca Blue Swirl
#else
40 163fa5ca Blue Swirl
41 163fa5ca Blue Swirl
#ifndef TARGET_SPARC64
42 163fa5ca Blue Swirl
/*
43 163fa5ca Blue Swirl
 * Sparc V8 Reference MMU (SRMMU)
44 163fa5ca Blue Swirl
 */
45 163fa5ca Blue Swirl
static const int access_table[8][8] = {
46 163fa5ca Blue Swirl
    { 0, 0, 0, 0, 8, 0, 12, 12 },
47 163fa5ca Blue Swirl
    { 0, 0, 0, 0, 8, 0, 0, 0 },
48 163fa5ca Blue Swirl
    { 8, 8, 0, 0, 0, 8, 12, 12 },
49 163fa5ca Blue Swirl
    { 8, 8, 0, 0, 0, 8, 0, 0 },
50 163fa5ca Blue Swirl
    { 8, 0, 8, 0, 8, 8, 12, 12 },
51 163fa5ca Blue Swirl
    { 8, 0, 8, 0, 8, 0, 8, 0 },
52 163fa5ca Blue Swirl
    { 8, 8, 8, 0, 8, 8, 12, 12 },
53 163fa5ca Blue Swirl
    { 8, 8, 8, 0, 8, 8, 8, 0 }
54 163fa5ca Blue Swirl
};
55 163fa5ca Blue Swirl
56 163fa5ca Blue Swirl
static const int perm_table[2][8] = {
57 163fa5ca Blue Swirl
    {
58 163fa5ca Blue Swirl
        PAGE_READ,
59 163fa5ca Blue Swirl
        PAGE_READ | PAGE_WRITE,
60 163fa5ca Blue Swirl
        PAGE_READ | PAGE_EXEC,
61 163fa5ca Blue Swirl
        PAGE_READ | PAGE_WRITE | PAGE_EXEC,
62 163fa5ca Blue Swirl
        PAGE_EXEC,
63 163fa5ca Blue Swirl
        PAGE_READ | PAGE_WRITE,
64 163fa5ca Blue Swirl
        PAGE_READ | PAGE_EXEC,
65 163fa5ca Blue Swirl
        PAGE_READ | PAGE_WRITE | PAGE_EXEC
66 163fa5ca Blue Swirl
    },
67 163fa5ca Blue Swirl
    {
68 163fa5ca Blue Swirl
        PAGE_READ,
69 163fa5ca Blue Swirl
        PAGE_READ | PAGE_WRITE,
70 163fa5ca Blue Swirl
        PAGE_READ | PAGE_EXEC,
71 163fa5ca Blue Swirl
        PAGE_READ | PAGE_WRITE | PAGE_EXEC,
72 163fa5ca Blue Swirl
        PAGE_EXEC,
73 163fa5ca Blue Swirl
        PAGE_READ,
74 163fa5ca Blue Swirl
        0,
75 163fa5ca Blue Swirl
        0,
76 163fa5ca Blue Swirl
    }
77 163fa5ca Blue Swirl
};
78 163fa5ca Blue Swirl
79 163fa5ca Blue Swirl
static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
80 163fa5ca Blue Swirl
                                int *prot, int *access_index,
81 163fa5ca Blue Swirl
                                target_ulong address, int rw, int mmu_idx,
82 163fa5ca Blue Swirl
                                target_ulong *page_size)
83 163fa5ca Blue Swirl
{
84 163fa5ca Blue Swirl
    int access_perms = 0;
85 163fa5ca Blue Swirl
    target_phys_addr_t pde_ptr;
86 163fa5ca Blue Swirl
    uint32_t pde;
87 163fa5ca Blue Swirl
    int error_code = 0, is_dirty, is_user;
88 163fa5ca Blue Swirl
    unsigned long page_offset;
89 163fa5ca Blue Swirl
90 163fa5ca Blue Swirl
    is_user = mmu_idx == MMU_USER_IDX;
91 163fa5ca Blue Swirl
92 163fa5ca Blue Swirl
    if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
93 163fa5ca Blue Swirl
        *page_size = TARGET_PAGE_SIZE;
94 163fa5ca Blue Swirl
        /* Boot mode: instruction fetches are taken from PROM */
95 163fa5ca Blue Swirl
        if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
96 163fa5ca Blue Swirl
            *physical = env->prom_addr | (address & 0x7ffffULL);
97 163fa5ca Blue Swirl
            *prot = PAGE_READ | PAGE_EXEC;
98 163fa5ca Blue Swirl
            return 0;
99 163fa5ca Blue Swirl
        }
100 163fa5ca Blue Swirl
        *physical = address;
101 163fa5ca Blue Swirl
        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
102 163fa5ca Blue Swirl
        return 0;
103 163fa5ca Blue Swirl
    }
104 163fa5ca Blue Swirl
105 163fa5ca Blue Swirl
    *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user ? 0 : 1);
106 163fa5ca Blue Swirl
    *physical = 0xffffffffffff0000ULL;
107 163fa5ca Blue Swirl
108 163fa5ca Blue Swirl
    /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
109 163fa5ca Blue Swirl
    /* Context base + context number */
110 163fa5ca Blue Swirl
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
111 163fa5ca Blue Swirl
    pde = ldl_phys(pde_ptr);
112 163fa5ca Blue Swirl
113 163fa5ca Blue Swirl
    /* Ctx pde */
114 163fa5ca Blue Swirl
    switch (pde & PTE_ENTRYTYPE_MASK) {
115 163fa5ca Blue Swirl
    default:
116 163fa5ca Blue Swirl
    case 0: /* Invalid */
117 163fa5ca Blue Swirl
        return 1 << 2;
118 163fa5ca Blue Swirl
    case 2: /* L0 PTE, maybe should not happen? */
119 163fa5ca Blue Swirl
    case 3: /* Reserved */
120 163fa5ca Blue Swirl
        return 4 << 2;
121 163fa5ca Blue Swirl
    case 1: /* L0 PDE */
122 163fa5ca Blue Swirl
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
123 163fa5ca Blue Swirl
        pde = ldl_phys(pde_ptr);
124 163fa5ca Blue Swirl
125 163fa5ca Blue Swirl
        switch (pde & PTE_ENTRYTYPE_MASK) {
126 163fa5ca Blue Swirl
        default:
127 163fa5ca Blue Swirl
        case 0: /* Invalid */
128 163fa5ca Blue Swirl
            return (1 << 8) | (1 << 2);
129 163fa5ca Blue Swirl
        case 3: /* Reserved */
130 163fa5ca Blue Swirl
            return (1 << 8) | (4 << 2);
131 163fa5ca Blue Swirl
        case 1: /* L1 PDE */
132 163fa5ca Blue Swirl
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
133 163fa5ca Blue Swirl
            pde = ldl_phys(pde_ptr);
134 163fa5ca Blue Swirl
135 163fa5ca Blue Swirl
            switch (pde & PTE_ENTRYTYPE_MASK) {
136 163fa5ca Blue Swirl
            default:
137 163fa5ca Blue Swirl
            case 0: /* Invalid */
138 163fa5ca Blue Swirl
                return (2 << 8) | (1 << 2);
139 163fa5ca Blue Swirl
            case 3: /* Reserved */
140 163fa5ca Blue Swirl
                return (2 << 8) | (4 << 2);
141 163fa5ca Blue Swirl
            case 1: /* L2 PDE */
142 163fa5ca Blue Swirl
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
143 163fa5ca Blue Swirl
                pde = ldl_phys(pde_ptr);
144 163fa5ca Blue Swirl
145 163fa5ca Blue Swirl
                switch (pde & PTE_ENTRYTYPE_MASK) {
146 163fa5ca Blue Swirl
                default:
147 163fa5ca Blue Swirl
                case 0: /* Invalid */
148 163fa5ca Blue Swirl
                    return (3 << 8) | (1 << 2);
149 163fa5ca Blue Swirl
                case 1: /* PDE, should not happen */
150 163fa5ca Blue Swirl
                case 3: /* Reserved */
151 163fa5ca Blue Swirl
                    return (3 << 8) | (4 << 2);
152 163fa5ca Blue Swirl
                case 2: /* L3 PTE */
153 163fa5ca Blue Swirl
                    page_offset = (address & TARGET_PAGE_MASK) &
154 163fa5ca Blue Swirl
                        (TARGET_PAGE_SIZE - 1);
155 163fa5ca Blue Swirl
                }
156 163fa5ca Blue Swirl
                *page_size = TARGET_PAGE_SIZE;
157 163fa5ca Blue Swirl
                break;
158 163fa5ca Blue Swirl
            case 2: /* L2 PTE */
159 163fa5ca Blue Swirl
                page_offset = address & 0x3ffff;
160 163fa5ca Blue Swirl
                *page_size = 0x40000;
161 163fa5ca Blue Swirl
            }
162 163fa5ca Blue Swirl
            break;
163 163fa5ca Blue Swirl
        case 2: /* L1 PTE */
164 163fa5ca Blue Swirl
            page_offset = address & 0xffffff;
165 163fa5ca Blue Swirl
            *page_size = 0x1000000;
166 163fa5ca Blue Swirl
        }
167 163fa5ca Blue Swirl
    }
168 163fa5ca Blue Swirl
169 163fa5ca Blue Swirl
    /* check access */
170 163fa5ca Blue Swirl
    access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
171 163fa5ca Blue Swirl
    error_code = access_table[*access_index][access_perms];
172 163fa5ca Blue Swirl
    if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user)) {
173 163fa5ca Blue Swirl
        return error_code;
174 163fa5ca Blue Swirl
    }
175 163fa5ca Blue Swirl
176 163fa5ca Blue Swirl
    /* update page modified and dirty bits */
177 163fa5ca Blue Swirl
    is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
178 163fa5ca Blue Swirl
    if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
179 163fa5ca Blue Swirl
        pde |= PG_ACCESSED_MASK;
180 163fa5ca Blue Swirl
        if (is_dirty) {
181 163fa5ca Blue Swirl
            pde |= PG_MODIFIED_MASK;
182 163fa5ca Blue Swirl
        }
183 163fa5ca Blue Swirl
        stl_phys_notdirty(pde_ptr, pde);
184 163fa5ca Blue Swirl
    }
185 163fa5ca Blue Swirl
186 163fa5ca Blue Swirl
    /* the page can be put in the TLB */
187 163fa5ca Blue Swirl
    *prot = perm_table[is_user][access_perms];
188 163fa5ca Blue Swirl
    if (!(pde & PG_MODIFIED_MASK)) {
189 163fa5ca Blue Swirl
        /* only set write access if already dirty... otherwise wait
190 163fa5ca Blue Swirl
           for dirty access */
191 163fa5ca Blue Swirl
        *prot &= ~PAGE_WRITE;
192 163fa5ca Blue Swirl
    }
193 163fa5ca Blue Swirl
194 163fa5ca Blue Swirl
    /* Even if large ptes, we map only one 4KB page in the cache to
195 163fa5ca Blue Swirl
       avoid filling it too fast */
196 163fa5ca Blue Swirl
    *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
197 163fa5ca Blue Swirl
    return error_code;
198 163fa5ca Blue Swirl
}
199 163fa5ca Blue Swirl
200 163fa5ca Blue Swirl
/* Perform address translation */
201 163fa5ca Blue Swirl
int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
202 163fa5ca Blue Swirl
                               int mmu_idx)
203 163fa5ca Blue Swirl
{
204 163fa5ca Blue Swirl
    target_phys_addr_t paddr;
205 163fa5ca Blue Swirl
    target_ulong vaddr;
206 163fa5ca Blue Swirl
    target_ulong page_size;
207 163fa5ca Blue Swirl
    int error_code = 0, prot, access_index;
208 163fa5ca Blue Swirl
209 163fa5ca Blue Swirl
    error_code = get_physical_address(env, &paddr, &prot, &access_index,
210 163fa5ca Blue Swirl
                                      address, rw, mmu_idx, &page_size);
211 163fa5ca Blue Swirl
    if (error_code == 0) {
212 163fa5ca Blue Swirl
        vaddr = address & TARGET_PAGE_MASK;
213 163fa5ca Blue Swirl
        paddr &= TARGET_PAGE_MASK;
214 163fa5ca Blue Swirl
#ifdef DEBUG_MMU
215 163fa5ca Blue Swirl
        printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
216 163fa5ca Blue Swirl
               TARGET_FMT_lx "\n", address, paddr, vaddr);
217 163fa5ca Blue Swirl
#endif
218 163fa5ca Blue Swirl
        tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
219 163fa5ca Blue Swirl
        return 0;
220 163fa5ca Blue Swirl
    }
221 163fa5ca Blue Swirl
222 163fa5ca Blue Swirl
    if (env->mmuregs[3]) { /* Fault status register */
223 163fa5ca Blue Swirl
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
224 163fa5ca Blue Swirl
    }
225 163fa5ca Blue Swirl
    env->mmuregs[3] |= (access_index << 5) | error_code | 2;
226 163fa5ca Blue Swirl
    env->mmuregs[4] = address; /* Fault address register */
227 163fa5ca Blue Swirl
228 163fa5ca Blue Swirl
    if ((env->mmuregs[0] & MMU_NF) || env->psret == 0)  {
229 163fa5ca Blue Swirl
        /* No fault mode: if a mapping is available, just override
230 163fa5ca Blue Swirl
           permissions. If no mapping is available, redirect accesses to
231 163fa5ca Blue Swirl
           neverland. Fake/overridden mappings will be flushed when
232 163fa5ca Blue Swirl
           switching to normal mode. */
233 163fa5ca Blue Swirl
        vaddr = address & TARGET_PAGE_MASK;
234 163fa5ca Blue Swirl
        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
235 163fa5ca Blue Swirl
        tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
236 163fa5ca Blue Swirl
        return 0;
237 163fa5ca Blue Swirl
    } else {
238 163fa5ca Blue Swirl
        if (rw & 2) {
239 163fa5ca Blue Swirl
            env->exception_index = TT_TFAULT;
240 163fa5ca Blue Swirl
        } else {
241 163fa5ca Blue Swirl
            env->exception_index = TT_DFAULT;
242 163fa5ca Blue Swirl
        }
243 163fa5ca Blue Swirl
        return 1;
244 163fa5ca Blue Swirl
    }
245 163fa5ca Blue Swirl
}
246 163fa5ca Blue Swirl
247 163fa5ca Blue Swirl
target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
248 163fa5ca Blue Swirl
{
249 163fa5ca Blue Swirl
    target_phys_addr_t pde_ptr;
250 163fa5ca Blue Swirl
    uint32_t pde;
251 163fa5ca Blue Swirl
252 163fa5ca Blue Swirl
    /* Context base + context number */
253 163fa5ca Blue Swirl
    pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
254 163fa5ca Blue Swirl
        (env->mmuregs[2] << 2);
255 163fa5ca Blue Swirl
    pde = ldl_phys(pde_ptr);
256 163fa5ca Blue Swirl
257 163fa5ca Blue Swirl
    switch (pde & PTE_ENTRYTYPE_MASK) {
258 163fa5ca Blue Swirl
    default:
259 163fa5ca Blue Swirl
    case 0: /* Invalid */
260 163fa5ca Blue Swirl
    case 2: /* PTE, maybe should not happen? */
261 163fa5ca Blue Swirl
    case 3: /* Reserved */
262 163fa5ca Blue Swirl
        return 0;
263 163fa5ca Blue Swirl
    case 1: /* L1 PDE */
264 163fa5ca Blue Swirl
        if (mmulev == 3) {
265 163fa5ca Blue Swirl
            return pde;
266 163fa5ca Blue Swirl
        }
267 163fa5ca Blue Swirl
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
268 163fa5ca Blue Swirl
        pde = ldl_phys(pde_ptr);
269 163fa5ca Blue Swirl
270 163fa5ca Blue Swirl
        switch (pde & PTE_ENTRYTYPE_MASK) {
271 163fa5ca Blue Swirl
        default:
272 163fa5ca Blue Swirl
        case 0: /* Invalid */
273 163fa5ca Blue Swirl
        case 3: /* Reserved */
274 163fa5ca Blue Swirl
            return 0;
275 163fa5ca Blue Swirl
        case 2: /* L1 PTE */
276 163fa5ca Blue Swirl
            return pde;
277 163fa5ca Blue Swirl
        case 1: /* L2 PDE */
278 163fa5ca Blue Swirl
            if (mmulev == 2) {
279 163fa5ca Blue Swirl
                return pde;
280 163fa5ca Blue Swirl
            }
281 163fa5ca Blue Swirl
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
282 163fa5ca Blue Swirl
            pde = ldl_phys(pde_ptr);
283 163fa5ca Blue Swirl
284 163fa5ca Blue Swirl
            switch (pde & PTE_ENTRYTYPE_MASK) {
285 163fa5ca Blue Swirl
            default:
286 163fa5ca Blue Swirl
            case 0: /* Invalid */
287 163fa5ca Blue Swirl
            case 3: /* Reserved */
288 163fa5ca Blue Swirl
                return 0;
289 163fa5ca Blue Swirl
            case 2: /* L2 PTE */
290 163fa5ca Blue Swirl
                return pde;
291 163fa5ca Blue Swirl
            case 1: /* L3 PDE */
292 163fa5ca Blue Swirl
                if (mmulev == 1) {
293 163fa5ca Blue Swirl
                    return pde;
294 163fa5ca Blue Swirl
                }
295 163fa5ca Blue Swirl
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
296 163fa5ca Blue Swirl
                pde = ldl_phys(pde_ptr);
297 163fa5ca Blue Swirl
298 163fa5ca Blue Swirl
                switch (pde & PTE_ENTRYTYPE_MASK) {
299 163fa5ca Blue Swirl
                default:
300 163fa5ca Blue Swirl
                case 0: /* Invalid */
301 163fa5ca Blue Swirl
                case 1: /* PDE, should not happen */
302 163fa5ca Blue Swirl
                case 3: /* Reserved */
303 163fa5ca Blue Swirl
                    return 0;
304 163fa5ca Blue Swirl
                case 2: /* L3 PTE */
305 163fa5ca Blue Swirl
                    return pde;
306 163fa5ca Blue Swirl
                }
307 163fa5ca Blue Swirl
            }
308 163fa5ca Blue Swirl
        }
309 163fa5ca Blue Swirl
    }
310 163fa5ca Blue Swirl
    return 0;
311 163fa5ca Blue Swirl
}
312 163fa5ca Blue Swirl
313 163fa5ca Blue Swirl
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
314 163fa5ca Blue Swirl
{
315 163fa5ca Blue Swirl
    target_ulong va, va1, va2;
316 163fa5ca Blue Swirl
    unsigned int n, m, o;
317 163fa5ca Blue Swirl
    target_phys_addr_t pde_ptr, pa;
318 163fa5ca Blue Swirl
    uint32_t pde;
319 163fa5ca Blue Swirl
320 163fa5ca Blue Swirl
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
321 163fa5ca Blue Swirl
    pde = ldl_phys(pde_ptr);
322 163fa5ca Blue Swirl
    (*cpu_fprintf)(f, "Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
323 163fa5ca Blue Swirl
                   (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
324 163fa5ca Blue Swirl
    for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
325 163fa5ca Blue Swirl
        pde = mmu_probe(env, va, 2);
326 163fa5ca Blue Swirl
        if (pde) {
327 163fa5ca Blue Swirl
            pa = cpu_get_phys_page_debug(env, va);
328 163fa5ca Blue Swirl
            (*cpu_fprintf)(f, "VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
329 163fa5ca Blue Swirl
                           " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
330 163fa5ca Blue Swirl
            for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
331 163fa5ca Blue Swirl
                pde = mmu_probe(env, va1, 1);
332 163fa5ca Blue Swirl
                if (pde) {
333 163fa5ca Blue Swirl
                    pa = cpu_get_phys_page_debug(env, va1);
334 163fa5ca Blue Swirl
                    (*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
335 163fa5ca Blue Swirl
                                   TARGET_FMT_plx " PDE: " TARGET_FMT_lx "\n",
336 163fa5ca Blue Swirl
                                   va1, pa, pde);
337 163fa5ca Blue Swirl
                    for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
338 163fa5ca Blue Swirl
                        pde = mmu_probe(env, va2, 0);
339 163fa5ca Blue Swirl
                        if (pde) {
340 163fa5ca Blue Swirl
                            pa = cpu_get_phys_page_debug(env, va2);
341 163fa5ca Blue Swirl
                            (*cpu_fprintf)(f, "  VA: " TARGET_FMT_lx ", PA: "
342 163fa5ca Blue Swirl
                                           TARGET_FMT_plx " PTE: "
343 163fa5ca Blue Swirl
                                           TARGET_FMT_lx "\n",
344 163fa5ca Blue Swirl
                                           va2, pa, pde);
345 163fa5ca Blue Swirl
                        }
346 163fa5ca Blue Swirl
                    }
347 163fa5ca Blue Swirl
                }
348 163fa5ca Blue Swirl
            }
349 163fa5ca Blue Swirl
        }
350 163fa5ca Blue Swirl
    }
351 163fa5ca Blue Swirl
}
352 163fa5ca Blue Swirl
353 163fa5ca Blue Swirl
/* Gdb expects all registers windows to be flushed in ram. This function handles
354 163fa5ca Blue Swirl
 * reads (and only reads) in stack frames as if windows were flushed. We assume
355 163fa5ca Blue Swirl
 * that the sparc ABI is followed.
356 163fa5ca Blue Swirl
 */
357 163fa5ca Blue Swirl
int target_memory_rw_debug(CPUState *env, target_ulong addr,
358 163fa5ca Blue Swirl
                           uint8_t *buf, int len, int is_write)
359 163fa5ca Blue Swirl
{
360 163fa5ca Blue Swirl
    int i;
361 163fa5ca Blue Swirl
    int len1;
362 163fa5ca Blue Swirl
    int cwp = env->cwp;
363 163fa5ca Blue Swirl
364 163fa5ca Blue Swirl
    if (!is_write) {
365 163fa5ca Blue Swirl
        for (i = 0; i < env->nwindows; i++) {
366 163fa5ca Blue Swirl
            int off;
367 163fa5ca Blue Swirl
            target_ulong fp = env->regbase[cwp * 16 + 22];
368 163fa5ca Blue Swirl
369 163fa5ca Blue Swirl
            /* Assume fp == 0 means end of frame.  */
370 163fa5ca Blue Swirl
            if (fp == 0) {
371 163fa5ca Blue Swirl
                break;
372 163fa5ca Blue Swirl
            }
373 163fa5ca Blue Swirl
374 163fa5ca Blue Swirl
            cwp = cpu_cwp_inc(env, cwp + 1);
375 163fa5ca Blue Swirl
376 163fa5ca Blue Swirl
            /* Invalid window ? */
377 163fa5ca Blue Swirl
            if (env->wim & (1 << cwp)) {
378 163fa5ca Blue Swirl
                break;
379 163fa5ca Blue Swirl
            }
380 163fa5ca Blue Swirl
381 163fa5ca Blue Swirl
            /* According to the ABI, the stack is growing downward.  */
382 163fa5ca Blue Swirl
            if (addr + len < fp) {
383 163fa5ca Blue Swirl
                break;
384 163fa5ca Blue Swirl
            }
385 163fa5ca Blue Swirl
386 163fa5ca Blue Swirl
            /* Not in this frame.  */
387 163fa5ca Blue Swirl
            if (addr > fp + 64) {
388 163fa5ca Blue Swirl
                continue;
389 163fa5ca Blue Swirl
            }
390 163fa5ca Blue Swirl
391 163fa5ca Blue Swirl
            /* Handle access before this window.  */
392 163fa5ca Blue Swirl
            if (addr < fp) {
393 163fa5ca Blue Swirl
                len1 = fp - addr;
394 163fa5ca Blue Swirl
                if (cpu_memory_rw_debug(env, addr, buf, len1, is_write) != 0) {
395 163fa5ca Blue Swirl
                    return -1;
396 163fa5ca Blue Swirl
                }
397 163fa5ca Blue Swirl
                addr += len1;
398 163fa5ca Blue Swirl
                len -= len1;
399 163fa5ca Blue Swirl
                buf += len1;
400 163fa5ca Blue Swirl
            }
401 163fa5ca Blue Swirl
402 163fa5ca Blue Swirl
            /* Access byte per byte to registers. Not very efficient but speed
403 163fa5ca Blue Swirl
             * is not critical.
404 163fa5ca Blue Swirl
             */
405 163fa5ca Blue Swirl
            off = addr - fp;
406 163fa5ca Blue Swirl
            len1 = 64 - off;
407 163fa5ca Blue Swirl
408 163fa5ca Blue Swirl
            if (len1 > len) {
409 163fa5ca Blue Swirl
                len1 = len;
410 163fa5ca Blue Swirl
            }
411 163fa5ca Blue Swirl
412 163fa5ca Blue Swirl
            for (; len1; len1--) {
413 163fa5ca Blue Swirl
                int reg = cwp * 16 + 8 + (off >> 2);
414 163fa5ca Blue Swirl
                union {
415 163fa5ca Blue Swirl
                    uint32_t v;
416 163fa5ca Blue Swirl
                    uint8_t c[4];
417 163fa5ca Blue Swirl
                } u;
418 163fa5ca Blue Swirl
                u.v = cpu_to_be32(env->regbase[reg]);
419 163fa5ca Blue Swirl
                *buf++ = u.c[off & 3];
420 163fa5ca Blue Swirl
                addr++;
421 163fa5ca Blue Swirl
                len--;
422 163fa5ca Blue Swirl
                off++;
423 163fa5ca Blue Swirl
            }
424 163fa5ca Blue Swirl
425 163fa5ca Blue Swirl
            if (len == 0) {
426 163fa5ca Blue Swirl
                return 0;
427 163fa5ca Blue Swirl
            }
428 163fa5ca Blue Swirl
        }
429 163fa5ca Blue Swirl
    }
430 163fa5ca Blue Swirl
    return cpu_memory_rw_debug(env, addr, buf, len, is_write);
431 163fa5ca Blue Swirl
}
432 163fa5ca Blue Swirl
433 163fa5ca Blue Swirl
#else /* !TARGET_SPARC64 */
434 163fa5ca Blue Swirl
435 163fa5ca Blue Swirl
/* 41 bit physical address space */
436 163fa5ca Blue Swirl
static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
437 163fa5ca Blue Swirl
{
438 163fa5ca Blue Swirl
    return x & 0x1ffffffffffULL;
439 163fa5ca Blue Swirl
}
440 163fa5ca Blue Swirl
441 163fa5ca Blue Swirl
/*
442 163fa5ca Blue Swirl
 * UltraSparc IIi I/DMMUs
443 163fa5ca Blue Swirl
 */
444 163fa5ca Blue Swirl
445 163fa5ca Blue Swirl
/* Returns true if TTE tag is valid and matches virtual address value
446 163fa5ca Blue Swirl
   in context requires virtual address mask value calculated from TTE
447 163fa5ca Blue Swirl
   entry size */
448 163fa5ca Blue Swirl
static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
449 163fa5ca Blue Swirl
                                       uint64_t address, uint64_t context,
450 163fa5ca Blue Swirl
                                       target_phys_addr_t *physical)
451 163fa5ca Blue Swirl
{
452 163fa5ca Blue Swirl
    uint64_t mask;
453 163fa5ca Blue Swirl
454 163fa5ca Blue Swirl
    switch (TTE_PGSIZE(tlb->tte)) {
455 163fa5ca Blue Swirl
    default:
456 163fa5ca Blue Swirl
    case 0x0: /* 8k */
457 163fa5ca Blue Swirl
        mask = 0xffffffffffffe000ULL;
458 163fa5ca Blue Swirl
        break;
459 163fa5ca Blue Swirl
    case 0x1: /* 64k */
460 163fa5ca Blue Swirl
        mask = 0xffffffffffff0000ULL;
461 163fa5ca Blue Swirl
        break;
462 163fa5ca Blue Swirl
    case 0x2: /* 512k */
463 163fa5ca Blue Swirl
        mask = 0xfffffffffff80000ULL;
464 163fa5ca Blue Swirl
        break;
465 163fa5ca Blue Swirl
    case 0x3: /* 4M */
466 163fa5ca Blue Swirl
        mask = 0xffffffffffc00000ULL;
467 163fa5ca Blue Swirl
        break;
468 163fa5ca Blue Swirl
    }
469 163fa5ca Blue Swirl
470 163fa5ca Blue Swirl
    /* valid, context match, virtual address match? */
471 163fa5ca Blue Swirl
    if (TTE_IS_VALID(tlb->tte) &&
472 163fa5ca Blue Swirl
        (TTE_IS_GLOBAL(tlb->tte) || tlb_compare_context(tlb, context))
473 163fa5ca Blue Swirl
        && compare_masked(address, tlb->tag, mask)) {
474 163fa5ca Blue Swirl
        /* decode physical address */
475 163fa5ca Blue Swirl
        *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
476 163fa5ca Blue Swirl
        return 1;
477 163fa5ca Blue Swirl
    }
478 163fa5ca Blue Swirl
479 163fa5ca Blue Swirl
    return 0;
480 163fa5ca Blue Swirl
}
481 163fa5ca Blue Swirl
482 163fa5ca Blue Swirl
static int get_physical_address_data(CPUState *env,
483 163fa5ca Blue Swirl
                                     target_phys_addr_t *physical, int *prot,
484 163fa5ca Blue Swirl
                                     target_ulong address, int rw, int mmu_idx)
485 163fa5ca Blue Swirl
{
486 163fa5ca Blue Swirl
    unsigned int i;
487 163fa5ca Blue Swirl
    uint64_t context;
488 163fa5ca Blue Swirl
    uint64_t sfsr = 0;
489 163fa5ca Blue Swirl
490 163fa5ca Blue Swirl
    int is_user = (mmu_idx == MMU_USER_IDX ||
491 163fa5ca Blue Swirl
                   mmu_idx == MMU_USER_SECONDARY_IDX);
492 163fa5ca Blue Swirl
493 163fa5ca Blue Swirl
    if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
494 163fa5ca Blue Swirl
        *physical = ultrasparc_truncate_physical(address);
495 163fa5ca Blue Swirl
        *prot = PAGE_READ | PAGE_WRITE;
496 163fa5ca Blue Swirl
        return 0;
497 163fa5ca Blue Swirl
    }
498 163fa5ca Blue Swirl
499 163fa5ca Blue Swirl
    switch (mmu_idx) {
500 163fa5ca Blue Swirl
    case MMU_USER_IDX:
501 163fa5ca Blue Swirl
    case MMU_KERNEL_IDX:
502 163fa5ca Blue Swirl
        context = env->dmmu.mmu_primary_context & 0x1fff;
503 163fa5ca Blue Swirl
        sfsr |= SFSR_CT_PRIMARY;
504 163fa5ca Blue Swirl
        break;
505 163fa5ca Blue Swirl
    case MMU_USER_SECONDARY_IDX:
506 163fa5ca Blue Swirl
    case MMU_KERNEL_SECONDARY_IDX:
507 163fa5ca Blue Swirl
        context = env->dmmu.mmu_secondary_context & 0x1fff;
508 163fa5ca Blue Swirl
        sfsr |= SFSR_CT_SECONDARY;
509 163fa5ca Blue Swirl
        break;
510 163fa5ca Blue Swirl
    case MMU_NUCLEUS_IDX:
511 163fa5ca Blue Swirl
        sfsr |= SFSR_CT_NUCLEUS;
512 163fa5ca Blue Swirl
        /* FALLTHRU */
513 163fa5ca Blue Swirl
    default:
514 163fa5ca Blue Swirl
        context = 0;
515 163fa5ca Blue Swirl
        break;
516 163fa5ca Blue Swirl
    }
517 163fa5ca Blue Swirl
518 163fa5ca Blue Swirl
    if (rw == 1) {
519 163fa5ca Blue Swirl
        sfsr |= SFSR_WRITE_BIT;
520 163fa5ca Blue Swirl
    } else if (rw == 4) {
521 163fa5ca Blue Swirl
        sfsr |= SFSR_NF_BIT;
522 163fa5ca Blue Swirl
    }
523 163fa5ca Blue Swirl
524 163fa5ca Blue Swirl
    for (i = 0; i < 64; i++) {
525 163fa5ca Blue Swirl
        /* ctx match, vaddr match, valid? */
526 163fa5ca Blue Swirl
        if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
527 163fa5ca Blue Swirl
            int do_fault = 0;
528 163fa5ca Blue Swirl
529 163fa5ca Blue Swirl
            /* access ok? */
530 163fa5ca Blue Swirl
            /* multiple bits in SFSR.FT may be set on TT_DFAULT */
531 163fa5ca Blue Swirl
            if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) {
532 163fa5ca Blue Swirl
                do_fault = 1;
533 163fa5ca Blue Swirl
                sfsr |= SFSR_FT_PRIV_BIT; /* privilege violation */
534 ec0ceb17 Blue Swirl
                trace_mmu_helper_dfault(address, context, mmu_idx, env->tl);
535 163fa5ca Blue Swirl
            }
536 163fa5ca Blue Swirl
            if (rw == 4) {
537 163fa5ca Blue Swirl
                if (TTE_IS_SIDEEFFECT(env->dtlb[i].tte)) {
538 163fa5ca Blue Swirl
                    do_fault = 1;
539 163fa5ca Blue Swirl
                    sfsr |= SFSR_FT_NF_E_BIT;
540 163fa5ca Blue Swirl
                }
541 163fa5ca Blue Swirl
            } else {
542 163fa5ca Blue Swirl
                if (TTE_IS_NFO(env->dtlb[i].tte)) {
543 163fa5ca Blue Swirl
                    do_fault = 1;
544 163fa5ca Blue Swirl
                    sfsr |= SFSR_FT_NFO_BIT;
545 163fa5ca Blue Swirl
                }
546 163fa5ca Blue Swirl
            }
547 163fa5ca Blue Swirl
548 163fa5ca Blue Swirl
            if (do_fault) {
549 163fa5ca Blue Swirl
                /* faults above are reported with TT_DFAULT. */
550 163fa5ca Blue Swirl
                env->exception_index = TT_DFAULT;
551 163fa5ca Blue Swirl
            } else if (!TTE_IS_W_OK(env->dtlb[i].tte) && (rw == 1)) {
552 163fa5ca Blue Swirl
                do_fault = 1;
553 163fa5ca Blue Swirl
                env->exception_index = TT_DPROT;
554 163fa5ca Blue Swirl
555 ec0ceb17 Blue Swirl
                trace_mmu_helper_dprot(address, context, mmu_idx, env->tl);
556 163fa5ca Blue Swirl
            }
557 163fa5ca Blue Swirl
558 163fa5ca Blue Swirl
            if (!do_fault) {
559 163fa5ca Blue Swirl
                *prot = PAGE_READ;
560 163fa5ca Blue Swirl
                if (TTE_IS_W_OK(env->dtlb[i].tte)) {
561 163fa5ca Blue Swirl
                    *prot |= PAGE_WRITE;
562 163fa5ca Blue Swirl
                }
563 163fa5ca Blue Swirl
564 163fa5ca Blue Swirl
                TTE_SET_USED(env->dtlb[i].tte);
565 163fa5ca Blue Swirl
566 163fa5ca Blue Swirl
                return 0;
567 163fa5ca Blue Swirl
            }
568 163fa5ca Blue Swirl
569 163fa5ca Blue Swirl
            if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */
570 163fa5ca Blue Swirl
                sfsr |= SFSR_OW_BIT; /* overflow (not read before
571 163fa5ca Blue Swirl
                                        another fault) */
572 163fa5ca Blue Swirl
            }
573 163fa5ca Blue Swirl
574 163fa5ca Blue Swirl
            if (env->pstate & PS_PRIV) {
575 163fa5ca Blue Swirl
                sfsr |= SFSR_PR_BIT;
576 163fa5ca Blue Swirl
            }
577 163fa5ca Blue Swirl
578 163fa5ca Blue Swirl
            /* FIXME: ASI field in SFSR must be set */
579 163fa5ca Blue Swirl
            env->dmmu.sfsr = sfsr | SFSR_VALID_BIT;
580 163fa5ca Blue Swirl
581 163fa5ca Blue Swirl
            env->dmmu.sfar = address; /* Fault address register */
582 163fa5ca Blue Swirl
583 163fa5ca Blue Swirl
            env->dmmu.tag_access = (address & ~0x1fffULL) | context;
584 163fa5ca Blue Swirl
585 163fa5ca Blue Swirl
            return 1;
586 163fa5ca Blue Swirl
        }
587 163fa5ca Blue Swirl
    }
588 163fa5ca Blue Swirl
589 ec0ceb17 Blue Swirl
    trace_mmu_helper_dmiss(address, context);
590 163fa5ca Blue Swirl
591 163fa5ca Blue Swirl
    /*
592 163fa5ca Blue Swirl
     * On MMU misses:
593 163fa5ca Blue Swirl
     * - UltraSPARC IIi: SFSR and SFAR unmodified
594 163fa5ca Blue Swirl
     * - JPS1: SFAR updated and some fields of SFSR updated
595 163fa5ca Blue Swirl
     */
596 163fa5ca Blue Swirl
    env->dmmu.tag_access = (address & ~0x1fffULL) | context;
597 163fa5ca Blue Swirl
    env->exception_index = TT_DMISS;
598 163fa5ca Blue Swirl
    return 1;
599 163fa5ca Blue Swirl
}
600 163fa5ca Blue Swirl
601 163fa5ca Blue Swirl
static int get_physical_address_code(CPUState *env,
602 163fa5ca Blue Swirl
                                     target_phys_addr_t *physical, int *prot,
603 163fa5ca Blue Swirl
                                     target_ulong address, int mmu_idx)
604 163fa5ca Blue Swirl
{
605 163fa5ca Blue Swirl
    unsigned int i;
606 163fa5ca Blue Swirl
    uint64_t context;
607 163fa5ca Blue Swirl
608 163fa5ca Blue Swirl
    int is_user = (mmu_idx == MMU_USER_IDX ||
609 163fa5ca Blue Swirl
                   mmu_idx == MMU_USER_SECONDARY_IDX);
610 163fa5ca Blue Swirl
611 163fa5ca Blue Swirl
    if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
612 163fa5ca Blue Swirl
        /* IMMU disabled */
613 163fa5ca Blue Swirl
        *physical = ultrasparc_truncate_physical(address);
614 163fa5ca Blue Swirl
        *prot = PAGE_EXEC;
615 163fa5ca Blue Swirl
        return 0;
616 163fa5ca Blue Swirl
    }
617 163fa5ca Blue Swirl
618 163fa5ca Blue Swirl
    if (env->tl == 0) {
619 163fa5ca Blue Swirl
        /* PRIMARY context */
620 163fa5ca Blue Swirl
        context = env->dmmu.mmu_primary_context & 0x1fff;
621 163fa5ca Blue Swirl
    } else {
622 163fa5ca Blue Swirl
        /* NUCLEUS context */
623 163fa5ca Blue Swirl
        context = 0;
624 163fa5ca Blue Swirl
    }
625 163fa5ca Blue Swirl
626 163fa5ca Blue Swirl
    for (i = 0; i < 64; i++) {
627 163fa5ca Blue Swirl
        /* ctx match, vaddr match, valid? */
628 163fa5ca Blue Swirl
        if (ultrasparc_tag_match(&env->itlb[i],
629 163fa5ca Blue Swirl
                                 address, context, physical)) {
630 163fa5ca Blue Swirl
            /* access ok? */
631 163fa5ca Blue Swirl
            if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
632 163fa5ca Blue Swirl
                /* Fault status register */
633 163fa5ca Blue Swirl
                if (env->immu.sfsr & SFSR_VALID_BIT) {
634 163fa5ca Blue Swirl
                    env->immu.sfsr = SFSR_OW_BIT; /* overflow (not read before
635 163fa5ca Blue Swirl
                                                     another fault) */
636 163fa5ca Blue Swirl
                } else {
637 163fa5ca Blue Swirl
                    env->immu.sfsr = 0;
638 163fa5ca Blue Swirl
                }
639 163fa5ca Blue Swirl
                if (env->pstate & PS_PRIV) {
640 163fa5ca Blue Swirl
                    env->immu.sfsr |= SFSR_PR_BIT;
641 163fa5ca Blue Swirl
                }
642 163fa5ca Blue Swirl
                if (env->tl > 0) {
643 163fa5ca Blue Swirl
                    env->immu.sfsr |= SFSR_CT_NUCLEUS;
644 163fa5ca Blue Swirl
                }
645 163fa5ca Blue Swirl
646 163fa5ca Blue Swirl
                /* FIXME: ASI field in SFSR must be set */
647 163fa5ca Blue Swirl
                env->immu.sfsr |= SFSR_FT_PRIV_BIT | SFSR_VALID_BIT;
648 163fa5ca Blue Swirl
                env->exception_index = TT_TFAULT;
649 163fa5ca Blue Swirl
650 163fa5ca Blue Swirl
                env->immu.tag_access = (address & ~0x1fffULL) | context;
651 163fa5ca Blue Swirl
652 ec0ceb17 Blue Swirl
                trace_mmu_helper_tfault(address, context);
653 163fa5ca Blue Swirl
654 163fa5ca Blue Swirl
                return 1;
655 163fa5ca Blue Swirl
            }
656 163fa5ca Blue Swirl
            *prot = PAGE_EXEC;
657 163fa5ca Blue Swirl
            TTE_SET_USED(env->itlb[i].tte);
658 163fa5ca Blue Swirl
            return 0;
659 163fa5ca Blue Swirl
        }
660 163fa5ca Blue Swirl
    }
661 163fa5ca Blue Swirl
662 ec0ceb17 Blue Swirl
    trace_mmu_helper_tmiss(address, context);
663 163fa5ca Blue Swirl
664 163fa5ca Blue Swirl
    /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
665 163fa5ca Blue Swirl
    env->immu.tag_access = (address & ~0x1fffULL) | context;
666 163fa5ca Blue Swirl
    env->exception_index = TT_TMISS;
667 163fa5ca Blue Swirl
    return 1;
668 163fa5ca Blue Swirl
}
669 163fa5ca Blue Swirl
670 163fa5ca Blue Swirl
static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
671 163fa5ca Blue Swirl
                                int *prot, int *access_index,
672 163fa5ca Blue Swirl
                                target_ulong address, int rw, int mmu_idx,
673 163fa5ca Blue Swirl
                                target_ulong *page_size)
674 163fa5ca Blue Swirl
{
675 163fa5ca Blue Swirl
    /* ??? We treat everything as a small page, then explicitly flush
676 163fa5ca Blue Swirl
       everything when an entry is evicted.  */
677 163fa5ca Blue Swirl
    *page_size = TARGET_PAGE_SIZE;
678 163fa5ca Blue Swirl
679 163fa5ca Blue Swirl
    /* safety net to catch wrong softmmu index use from dynamic code */
680 163fa5ca Blue Swirl
    if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
681 ec0ceb17 Blue Swirl
        if (rw == 2) {
682 ec0ceb17 Blue Swirl
            trace_mmu_helper_get_phys_addr_code(env->tl, mmu_idx,
683 ec0ceb17 Blue Swirl
                                                env->dmmu.mmu_primary_context,
684 ec0ceb17 Blue Swirl
                                                env->dmmu.mmu_secondary_context,
685 ec0ceb17 Blue Swirl
                                                address);
686 ec0ceb17 Blue Swirl
        } else {
687 ec0ceb17 Blue Swirl
            trace_mmu_helper_get_phys_addr_data(env->tl, mmu_idx,
688 ec0ceb17 Blue Swirl
                                                env->dmmu.mmu_primary_context,
689 ec0ceb17 Blue Swirl
                                                env->dmmu.mmu_secondary_context,
690 ec0ceb17 Blue Swirl
                                                address);
691 ec0ceb17 Blue Swirl
        }
692 163fa5ca Blue Swirl
    }
693 163fa5ca Blue Swirl
694 163fa5ca Blue Swirl
    if (rw == 2) {
695 163fa5ca Blue Swirl
        return get_physical_address_code(env, physical, prot, address,
696 163fa5ca Blue Swirl
                                         mmu_idx);
697 163fa5ca Blue Swirl
    } else {
698 163fa5ca Blue Swirl
        return get_physical_address_data(env, physical, prot, address, rw,
699 163fa5ca Blue Swirl
                                         mmu_idx);
700 163fa5ca Blue Swirl
    }
701 163fa5ca Blue Swirl
}
702 163fa5ca Blue Swirl
703 163fa5ca Blue Swirl
/* Perform address translation */
704 163fa5ca Blue Swirl
int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
705 163fa5ca Blue Swirl
                               int mmu_idx)
706 163fa5ca Blue Swirl
{
707 163fa5ca Blue Swirl
    target_ulong virt_addr, vaddr;
708 163fa5ca Blue Swirl
    target_phys_addr_t paddr;
709 163fa5ca Blue Swirl
    target_ulong page_size;
710 163fa5ca Blue Swirl
    int error_code = 0, prot, access_index;
711 163fa5ca Blue Swirl
712 163fa5ca Blue Swirl
    error_code = get_physical_address(env, &paddr, &prot, &access_index,
713 163fa5ca Blue Swirl
                                      address, rw, mmu_idx, &page_size);
714 163fa5ca Blue Swirl
    if (error_code == 0) {
715 163fa5ca Blue Swirl
        virt_addr = address & TARGET_PAGE_MASK;
716 163fa5ca Blue Swirl
        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
717 163fa5ca Blue Swirl
                             (TARGET_PAGE_SIZE - 1));
718 163fa5ca Blue Swirl
719 ec0ceb17 Blue Swirl
        trace_mmu_helper_mmu_fault(address, paddr, mmu_idx, env->tl,
720 ec0ceb17 Blue Swirl
                                   env->dmmu.mmu_primary_context,
721 ec0ceb17 Blue Swirl
                                   env->dmmu.mmu_secondary_context);
722 163fa5ca Blue Swirl
723 163fa5ca Blue Swirl
        tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
724 163fa5ca Blue Swirl
        return 0;
725 163fa5ca Blue Swirl
    }
726 163fa5ca Blue Swirl
    /* XXX */
727 163fa5ca Blue Swirl
    return 1;
728 163fa5ca Blue Swirl
}
729 163fa5ca Blue Swirl
730 163fa5ca Blue Swirl
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
731 163fa5ca Blue Swirl
{
732 163fa5ca Blue Swirl
    unsigned int i;
733 163fa5ca Blue Swirl
    const char *mask;
734 163fa5ca Blue Swirl
735 163fa5ca Blue Swirl
    (*cpu_fprintf)(f, "MMU contexts: Primary: %" PRId64 ", Secondary: %"
736 163fa5ca Blue Swirl
                   PRId64 "\n",
737 163fa5ca Blue Swirl
                   env->dmmu.mmu_primary_context,
738 163fa5ca Blue Swirl
                   env->dmmu.mmu_secondary_context);
739 163fa5ca Blue Swirl
    if ((env->lsu & DMMU_E) == 0) {
740 163fa5ca Blue Swirl
        (*cpu_fprintf)(f, "DMMU disabled\n");
741 163fa5ca Blue Swirl
    } else {
742 163fa5ca Blue Swirl
        (*cpu_fprintf)(f, "DMMU dump\n");
743 163fa5ca Blue Swirl
        for (i = 0; i < 64; i++) {
744 163fa5ca Blue Swirl
            switch (TTE_PGSIZE(env->dtlb[i].tte)) {
745 163fa5ca Blue Swirl
            default:
746 163fa5ca Blue Swirl
            case 0x0:
747 163fa5ca Blue Swirl
                mask = "  8k";
748 163fa5ca Blue Swirl
                break;
749 163fa5ca Blue Swirl
            case 0x1:
750 163fa5ca Blue Swirl
                mask = " 64k";
751 163fa5ca Blue Swirl
                break;
752 163fa5ca Blue Swirl
            case 0x2:
753 163fa5ca Blue Swirl
                mask = "512k";
754 163fa5ca Blue Swirl
                break;
755 163fa5ca Blue Swirl
            case 0x3:
756 163fa5ca Blue Swirl
                mask = "  4M";
757 163fa5ca Blue Swirl
                break;
758 163fa5ca Blue Swirl
            }
759 163fa5ca Blue Swirl
            if (TTE_IS_VALID(env->dtlb[i].tte)) {
760 163fa5ca Blue Swirl
                (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %llx"
761 163fa5ca Blue Swirl
                               ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
762 163fa5ca Blue Swirl
                               i,
763 163fa5ca Blue Swirl
                               env->dtlb[i].tag & (uint64_t)~0x1fffULL,
764 163fa5ca Blue Swirl
                               TTE_PA(env->dtlb[i].tte),
765 163fa5ca Blue Swirl
                               mask,
766 163fa5ca Blue Swirl
                               TTE_IS_PRIV(env->dtlb[i].tte) ? "priv" : "user",
767 163fa5ca Blue Swirl
                               TTE_IS_W_OK(env->dtlb[i].tte) ? "RW" : "RO",
768 163fa5ca Blue Swirl
                               TTE_IS_LOCKED(env->dtlb[i].tte) ?
769 163fa5ca Blue Swirl
                               "locked" : "unlocked",
770 163fa5ca Blue Swirl
                               env->dtlb[i].tag & (uint64_t)0x1fffULL,
771 163fa5ca Blue Swirl
                               TTE_IS_GLOBAL(env->dtlb[i].tte) ?
772 163fa5ca Blue Swirl
                               "global" : "local");
773 163fa5ca Blue Swirl
            }
774 163fa5ca Blue Swirl
        }
775 163fa5ca Blue Swirl
    }
776 163fa5ca Blue Swirl
    if ((env->lsu & IMMU_E) == 0) {
777 163fa5ca Blue Swirl
        (*cpu_fprintf)(f, "IMMU disabled\n");
778 163fa5ca Blue Swirl
    } else {
779 163fa5ca Blue Swirl
        (*cpu_fprintf)(f, "IMMU dump\n");
780 163fa5ca Blue Swirl
        for (i = 0; i < 64; i++) {
781 163fa5ca Blue Swirl
            switch (TTE_PGSIZE(env->itlb[i].tte)) {
782 163fa5ca Blue Swirl
            default:
783 163fa5ca Blue Swirl
            case 0x0:
784 163fa5ca Blue Swirl
                mask = "  8k";
785 163fa5ca Blue Swirl
                break;
786 163fa5ca Blue Swirl
            case 0x1:
787 163fa5ca Blue Swirl
                mask = " 64k";
788 163fa5ca Blue Swirl
                break;
789 163fa5ca Blue Swirl
            case 0x2:
790 163fa5ca Blue Swirl
                mask = "512k";
791 163fa5ca Blue Swirl
                break;
792 163fa5ca Blue Swirl
            case 0x3:
793 163fa5ca Blue Swirl
                mask = "  4M";
794 163fa5ca Blue Swirl
                break;
795 163fa5ca Blue Swirl
            }
796 163fa5ca Blue Swirl
            if (TTE_IS_VALID(env->itlb[i].tte)) {
797 163fa5ca Blue Swirl
                (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %llx"
798 163fa5ca Blue Swirl
                               ", %s, %s, %s, ctx %" PRId64 " %s\n",
799 163fa5ca Blue Swirl
                               i,
800 163fa5ca Blue Swirl
                               env->itlb[i].tag & (uint64_t)~0x1fffULL,
801 163fa5ca Blue Swirl
                               TTE_PA(env->itlb[i].tte),
802 163fa5ca Blue Swirl
                               mask,
803 163fa5ca Blue Swirl
                               TTE_IS_PRIV(env->itlb[i].tte) ? "priv" : "user",
804 163fa5ca Blue Swirl
                               TTE_IS_LOCKED(env->itlb[i].tte) ?
805 163fa5ca Blue Swirl
                               "locked" : "unlocked",
806 163fa5ca Blue Swirl
                               env->itlb[i].tag & (uint64_t)0x1fffULL,
807 163fa5ca Blue Swirl
                               TTE_IS_GLOBAL(env->itlb[i].tte) ?
808 163fa5ca Blue Swirl
                               "global" : "local");
809 163fa5ca Blue Swirl
            }
810 163fa5ca Blue Swirl
        }
811 163fa5ca Blue Swirl
    }
812 163fa5ca Blue Swirl
}
813 163fa5ca Blue Swirl
814 163fa5ca Blue Swirl
#endif /* TARGET_SPARC64 */
815 163fa5ca Blue Swirl
816 163fa5ca Blue Swirl
static int cpu_sparc_get_phys_page(CPUState *env, target_phys_addr_t *phys,
817 163fa5ca Blue Swirl
                                   target_ulong addr, int rw, int mmu_idx)
818 163fa5ca Blue Swirl
{
819 163fa5ca Blue Swirl
    target_ulong page_size;
820 163fa5ca Blue Swirl
    int prot, access_index;
821 163fa5ca Blue Swirl
822 163fa5ca Blue Swirl
    return get_physical_address(env, phys, &prot, &access_index, addr, rw,
823 163fa5ca Blue Swirl
                                mmu_idx, &page_size);
824 163fa5ca Blue Swirl
}
825 163fa5ca Blue Swirl
826 163fa5ca Blue Swirl
#if defined(TARGET_SPARC64)
827 163fa5ca Blue Swirl
target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
828 163fa5ca Blue Swirl
                                           int mmu_idx)
829 163fa5ca Blue Swirl
{
830 163fa5ca Blue Swirl
    target_phys_addr_t phys_addr;
831 163fa5ca Blue Swirl
832 163fa5ca Blue Swirl
    if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 4, mmu_idx) != 0) {
833 163fa5ca Blue Swirl
        return -1;
834 163fa5ca Blue Swirl
    }
835 163fa5ca Blue Swirl
    return phys_addr;
836 163fa5ca Blue Swirl
}
837 163fa5ca Blue Swirl
#endif
838 163fa5ca Blue Swirl
839 163fa5ca Blue Swirl
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
840 163fa5ca Blue Swirl
{
841 163fa5ca Blue Swirl
    target_phys_addr_t phys_addr;
842 163fa5ca Blue Swirl
    int mmu_idx = cpu_mmu_index(env);
843 cc4aa830 Avi Kivity
    MemoryRegionSection section;
844 163fa5ca Blue Swirl
845 163fa5ca Blue Swirl
    if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 2, mmu_idx) != 0) {
846 163fa5ca Blue Swirl
        if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) {
847 163fa5ca Blue Swirl
            return -1;
848 163fa5ca Blue Swirl
        }
849 163fa5ca Blue Swirl
    }
850 cc4aa830 Avi Kivity
    section = memory_region_find(get_system_memory(), phys_addr, 1);
851 cc4aa830 Avi Kivity
    if (!section.size) {
852 163fa5ca Blue Swirl
        return -1;
853 163fa5ca Blue Swirl
    }
854 163fa5ca Blue Swirl
    return phys_addr;
855 163fa5ca Blue Swirl
}
856 163fa5ca Blue Swirl
#endif