Statistics
| Branch: | Revision:

root / target-sparc / helper.c @ ee5bbe38

History | View | Annotate | Download (13 kB)

1 e8af50a3 bellard
/*
2 e8af50a3 bellard
 *  sparc helpers
3 e8af50a3 bellard
 * 
4 e8af50a3 bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 e8af50a3 bellard
 *
6 e8af50a3 bellard
 * This library is free software; you can redistribute it and/or
7 e8af50a3 bellard
 * modify it under the terms of the GNU Lesser General Public
8 e8af50a3 bellard
 * License as published by the Free Software Foundation; either
9 e8af50a3 bellard
 * version 2 of the License, or (at your option) any later version.
10 e8af50a3 bellard
 *
11 e8af50a3 bellard
 * This library is distributed in the hope that it will be useful,
12 e8af50a3 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 e8af50a3 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 e8af50a3 bellard
 * Lesser General Public License for more details.
15 e8af50a3 bellard
 *
16 e8af50a3 bellard
 * You should have received a copy of the GNU Lesser General Public
17 e8af50a3 bellard
 * License along with this library; if not, write to the Free Software
18 e8af50a3 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 e8af50a3 bellard
 */
20 ee5bbe38 bellard
#include <stdarg.h>
21 ee5bbe38 bellard
#include <stdlib.h>
22 ee5bbe38 bellard
#include <stdio.h>
23 ee5bbe38 bellard
#include <string.h>
24 ee5bbe38 bellard
#include <inttypes.h>
25 ee5bbe38 bellard
#include <signal.h>
26 ee5bbe38 bellard
#include <assert.h>
27 ee5bbe38 bellard
28 ee5bbe38 bellard
#include "cpu.h"
29 ee5bbe38 bellard
#include "exec-all.h"
30 e8af50a3 bellard
31 e80cfcfc bellard
//#define DEBUG_PCALL
32 e80cfcfc bellard
//#define DEBUG_MMU
33 e8af50a3 bellard
34 e8af50a3 bellard
/* Sparc MMU emulation */
35 e8af50a3 bellard
36 e8af50a3 bellard
/* thread support */
37 e8af50a3 bellard
38 e8af50a3 bellard
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
39 e8af50a3 bellard
40 e8af50a3 bellard
void cpu_lock(void)
41 e8af50a3 bellard
{
42 e8af50a3 bellard
    spin_lock(&global_cpu_lock);
43 e8af50a3 bellard
}
44 e8af50a3 bellard
45 e8af50a3 bellard
void cpu_unlock(void)
46 e8af50a3 bellard
{
47 e8af50a3 bellard
    spin_unlock(&global_cpu_lock);
48 e8af50a3 bellard
}
49 e8af50a3 bellard
50 9d893301 bellard
#if defined(CONFIG_USER_ONLY) 
51 9d893301 bellard
52 9d893301 bellard
int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
53 9d893301 bellard
                               int is_user, int is_softmmu)
54 9d893301 bellard
{
55 878d3096 bellard
    if (rw & 2)
56 878d3096 bellard
        env->exception_index = TT_TFAULT;
57 878d3096 bellard
    else
58 878d3096 bellard
        env->exception_index = TT_DFAULT;
59 9d893301 bellard
    return 1;
60 9d893301 bellard
}
61 9d893301 bellard
62 9d893301 bellard
#else
63 e8af50a3 bellard
64 3475187d bellard
#ifndef TARGET_SPARC64
65 e8af50a3 bellard
static const int access_table[8][8] = {
66 e8af50a3 bellard
    { 0, 0, 0, 0, 2, 0, 3, 3 },
67 e8af50a3 bellard
    { 0, 0, 0, 0, 2, 0, 0, 0 },
68 e8af50a3 bellard
    { 2, 2, 0, 0, 0, 2, 3, 3 },
69 e8af50a3 bellard
    { 2, 2, 0, 0, 0, 2, 0, 0 },
70 e8af50a3 bellard
    { 2, 0, 2, 0, 2, 2, 3, 3 },
71 e8af50a3 bellard
    { 2, 0, 2, 0, 2, 0, 2, 0 },
72 e8af50a3 bellard
    { 2, 2, 2, 0, 2, 2, 3, 3 },
73 e8af50a3 bellard
    { 2, 2, 2, 0, 2, 2, 2, 0 }
74 e8af50a3 bellard
};
75 e8af50a3 bellard
76 e8af50a3 bellard
/* 1 = write OK */
77 e8af50a3 bellard
static const int rw_table[2][8] = {
78 e8af50a3 bellard
    { 0, 1, 0, 1, 0, 1, 0, 1 },
79 e8af50a3 bellard
    { 0, 1, 0, 1, 0, 0, 0, 0 }
80 e8af50a3 bellard
};
81 e8af50a3 bellard
82 af7bf89b bellard
int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
83 af7bf89b bellard
                          int *access_index, target_ulong address, int rw,
84 e80cfcfc bellard
                          int is_user)
85 e8af50a3 bellard
{
86 e80cfcfc bellard
    int access_perms = 0;
87 e80cfcfc bellard
    target_phys_addr_t pde_ptr;
88 af7bf89b bellard
    uint32_t pde;
89 af7bf89b bellard
    target_ulong virt_addr;
90 e80cfcfc bellard
    int error_code = 0, is_dirty;
91 e80cfcfc bellard
    unsigned long page_offset;
92 e8af50a3 bellard
93 e8af50a3 bellard
    virt_addr = address & TARGET_PAGE_MASK;
94 e8af50a3 bellard
    if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
95 e80cfcfc bellard
        *physical = address;
96 e80cfcfc bellard
        *prot = PAGE_READ | PAGE_WRITE;
97 e80cfcfc bellard
        return 0;
98 e8af50a3 bellard
    }
99 e8af50a3 bellard
100 7483750d bellard
    *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
101 6f7e9aec bellard
    *physical = 0xfffff000;
102 7483750d bellard
103 e8af50a3 bellard
    /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
104 e8af50a3 bellard
    /* Context base + context number */
105 b3180cdc bellard
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
106 49be8030 bellard
    pde = ldl_phys(pde_ptr);
107 e8af50a3 bellard
108 e8af50a3 bellard
    /* Ctx pde */
109 e8af50a3 bellard
    switch (pde & PTE_ENTRYTYPE_MASK) {
110 e80cfcfc bellard
    default:
111 e8af50a3 bellard
    case 0: /* Invalid */
112 7483750d bellard
        return 1 << 2;
113 e80cfcfc bellard
    case 2: /* L0 PTE, maybe should not happen? */
114 e8af50a3 bellard
    case 3: /* Reserved */
115 7483750d bellard
        return 4 << 2;
116 e80cfcfc bellard
    case 1: /* L0 PDE */
117 e80cfcfc bellard
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
118 49be8030 bellard
        pde = ldl_phys(pde_ptr);
119 e8af50a3 bellard
120 e8af50a3 bellard
        switch (pde & PTE_ENTRYTYPE_MASK) {
121 e80cfcfc bellard
        default:
122 e8af50a3 bellard
        case 0: /* Invalid */
123 7483750d bellard
            return (1 << 8) | (1 << 2);
124 e8af50a3 bellard
        case 3: /* Reserved */
125 7483750d bellard
            return (1 << 8) | (4 << 2);
126 e80cfcfc bellard
        case 1: /* L1 PDE */
127 e80cfcfc bellard
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
128 49be8030 bellard
            pde = ldl_phys(pde_ptr);
129 e8af50a3 bellard
130 e8af50a3 bellard
            switch (pde & PTE_ENTRYTYPE_MASK) {
131 e80cfcfc bellard
            default:
132 e8af50a3 bellard
            case 0: /* Invalid */
133 7483750d bellard
                return (2 << 8) | (1 << 2);
134 e8af50a3 bellard
            case 3: /* Reserved */
135 7483750d bellard
                return (2 << 8) | (4 << 2);
136 e80cfcfc bellard
            case 1: /* L2 PDE */
137 e80cfcfc bellard
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
138 49be8030 bellard
                pde = ldl_phys(pde_ptr);
139 e8af50a3 bellard
140 e8af50a3 bellard
                switch (pde & PTE_ENTRYTYPE_MASK) {
141 e80cfcfc bellard
                default:
142 e8af50a3 bellard
                case 0: /* Invalid */
143 7483750d bellard
                    return (3 << 8) | (1 << 2);
144 e8af50a3 bellard
                case 1: /* PDE, should not happen */
145 e8af50a3 bellard
                case 3: /* Reserved */
146 7483750d bellard
                    return (3 << 8) | (4 << 2);
147 e8af50a3 bellard
                case 2: /* L3 PTE */
148 e8af50a3 bellard
                    virt_addr = address & TARGET_PAGE_MASK;
149 e8af50a3 bellard
                    page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1);
150 e8af50a3 bellard
                }
151 e8af50a3 bellard
                break;
152 e8af50a3 bellard
            case 2: /* L2 PTE */
153 e8af50a3 bellard
                virt_addr = address & ~0x3ffff;
154 e8af50a3 bellard
                page_offset = address & 0x3ffff;
155 e8af50a3 bellard
            }
156 e8af50a3 bellard
            break;
157 e8af50a3 bellard
        case 2: /* L1 PTE */
158 e8af50a3 bellard
            virt_addr = address & ~0xffffff;
159 e8af50a3 bellard
            page_offset = address & 0xffffff;
160 e8af50a3 bellard
        }
161 e8af50a3 bellard
    }
162 e8af50a3 bellard
163 e8af50a3 bellard
    /* update page modified and dirty bits */
164 b769d8fe bellard
    is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
165 e8af50a3 bellard
    if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
166 e8af50a3 bellard
        pde |= PG_ACCESSED_MASK;
167 e8af50a3 bellard
        if (is_dirty)
168 e8af50a3 bellard
            pde |= PG_MODIFIED_MASK;
169 49be8030 bellard
        stl_phys_notdirty(pde_ptr, pde);
170 e8af50a3 bellard
    }
171 e8af50a3 bellard
    /* check access */
172 e8af50a3 bellard
    access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
173 e80cfcfc bellard
    error_code = access_table[*access_index][access_perms];
174 6f7e9aec bellard
    if (error_code && !(env->mmuregs[0] & MMU_NF))
175 e80cfcfc bellard
        return error_code;
176 e8af50a3 bellard
177 e8af50a3 bellard
    /* the page can be put in the TLB */
178 e80cfcfc bellard
    *prot = PAGE_READ;
179 e8af50a3 bellard
    if (pde & PG_MODIFIED_MASK) {
180 e8af50a3 bellard
        /* only set write access if already dirty... otherwise wait
181 e8af50a3 bellard
           for dirty access */
182 e8af50a3 bellard
        if (rw_table[is_user][access_perms])
183 e80cfcfc bellard
                *prot |= PAGE_WRITE;
184 e8af50a3 bellard
    }
185 e8af50a3 bellard
186 e8af50a3 bellard
    /* Even if large ptes, we map only one 4KB page in the cache to
187 e8af50a3 bellard
       avoid filling it too fast */
188 e80cfcfc bellard
    *physical = ((pde & PTE_ADDR_MASK) << 4) + page_offset;
189 6f7e9aec bellard
    return error_code;
190 e80cfcfc bellard
}
191 e80cfcfc bellard
192 e80cfcfc bellard
/* Perform address translation */
193 af7bf89b bellard
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
194 e80cfcfc bellard
                              int is_user, int is_softmmu)
195 e80cfcfc bellard
{
196 af7bf89b bellard
    target_ulong virt_addr;
197 af7bf89b bellard
    target_phys_addr_t paddr;
198 e80cfcfc bellard
    unsigned long vaddr;
199 e80cfcfc bellard
    int error_code = 0, prot, ret = 0, access_index;
200 e8af50a3 bellard
201 e80cfcfc bellard
    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
202 e80cfcfc bellard
    if (error_code == 0) {
203 e80cfcfc bellard
        virt_addr = address & TARGET_PAGE_MASK;
204 e80cfcfc bellard
        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
205 e80cfcfc bellard
        ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
206 e80cfcfc bellard
        return ret;
207 e80cfcfc bellard
    }
208 e8af50a3 bellard
209 e8af50a3 bellard
    if (env->mmuregs[3]) /* Fault status register */
210 e8af50a3 bellard
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
211 7483750d bellard
    env->mmuregs[3] |= (access_index << 5) | error_code | 2;
212 e8af50a3 bellard
    env->mmuregs[4] = address; /* Fault address register */
213 e8af50a3 bellard
214 878d3096 bellard
    if ((env->mmuregs[0] & MMU_NF) || env->psret == 0)  {
215 6f7e9aec bellard
        // No fault mode: if a mapping is available, just override
216 6f7e9aec bellard
        // permissions. If no mapping is available, redirect accesses to
217 6f7e9aec bellard
        // neverland. Fake/overridden mappings will be flushed when
218 6f7e9aec bellard
        // switching to normal mode.
219 7483750d bellard
        vaddr = address & TARGET_PAGE_MASK;
220 7483750d bellard
        prot = PAGE_READ | PAGE_WRITE;
221 7483750d bellard
        ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
222 7483750d bellard
        return ret;
223 7483750d bellard
    } else {
224 7483750d bellard
        if (rw & 2)
225 7483750d bellard
            env->exception_index = TT_TFAULT;
226 7483750d bellard
        else
227 7483750d bellard
            env->exception_index = TT_DFAULT;
228 7483750d bellard
        return 1;
229 878d3096 bellard
    }
230 e8af50a3 bellard
}
231 3475187d bellard
#else
232 3475187d bellard
static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot,
233 3475187d bellard
                          int *access_index, target_ulong address, int rw,
234 3475187d bellard
                          int is_user)
235 3475187d bellard
{
236 3475187d bellard
    target_ulong mask;
237 3475187d bellard
    unsigned int i;
238 3475187d bellard
239 3475187d bellard
    if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
240 3475187d bellard
        *physical = address & 0xffffffff;
241 3475187d bellard
        *prot = PAGE_READ | PAGE_WRITE;
242 3475187d bellard
        return 0;
243 3475187d bellard
    }
244 3475187d bellard
245 3475187d bellard
    for (i = 0; i < 64; i++) {
246 3475187d bellard
        if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
247 3475187d bellard
            switch (env->dtlb_tte[i] >> 60) {
248 3475187d bellard
            default:
249 3475187d bellard
            case 0x4: // 8k
250 3475187d bellard
                mask = 0xffffffffffffe000ULL;
251 3475187d bellard
                break;
252 3475187d bellard
            case 0x5: // 64k
253 3475187d bellard
                mask = 0xffffffffffff0000ULL;
254 3475187d bellard
                break;
255 3475187d bellard
            case 0x6: // 512k
256 3475187d bellard
                mask = 0xfffffffffff80000ULL;
257 3475187d bellard
                break;
258 3475187d bellard
            case 0x7: // 4M
259 3475187d bellard
                mask = 0xffffffffffc00000ULL;
260 3475187d bellard
                break;
261 3475187d bellard
            }
262 3475187d bellard
            // ctx match, vaddr match?
263 3475187d bellard
            if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
264 3475187d bellard
                (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
265 3475187d bellard
                // access ok?
266 3475187d bellard
                if (((env->dtlb_tte[i] & 0x4) && !(env->pstate & PS_PRIV)) ||
267 3475187d bellard
                    (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
268 3475187d bellard
                    env->exception_index = TT_DFAULT;
269 3475187d bellard
                    return 1;
270 3475187d bellard
                }
271 3475187d bellard
                *physical = env->dtlb_tte[i] & 0xffffe000;
272 3475187d bellard
                *prot = PAGE_READ;
273 3475187d bellard
                if (env->dtlb_tte[i] & 0x2)
274 3475187d bellard
                    *prot |= PAGE_WRITE;
275 3475187d bellard
                return 0;
276 3475187d bellard
            }
277 3475187d bellard
        }
278 3475187d bellard
    }
279 3475187d bellard
    env->exception_index = TT_DFAULT;
280 3475187d bellard
    return 1;
281 3475187d bellard
}
282 3475187d bellard
283 3475187d bellard
static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical, int *prot,
284 3475187d bellard
                          int *access_index, target_ulong address, int rw,
285 3475187d bellard
                          int is_user)
286 3475187d bellard
{
287 3475187d bellard
    target_ulong mask;
288 3475187d bellard
    unsigned int i;
289 3475187d bellard
290 3475187d bellard
    if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
291 3475187d bellard
        *physical = address & 0xffffffff;
292 3475187d bellard
        *prot = PAGE_READ;
293 3475187d bellard
        return 0;
294 3475187d bellard
    }
295 3475187d bellard
    for (i = 0; i < 64; i++) {
296 3475187d bellard
        if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
297 3475187d bellard
            switch (env->itlb_tte[i] >> 60) {
298 3475187d bellard
            default:
299 3475187d bellard
            case 0x4: // 8k
300 3475187d bellard
                mask = 0xffffffffffffe000ULL;
301 3475187d bellard
                break;
302 3475187d bellard
            case 0x5: // 64k
303 3475187d bellard
                mask = 0xffffffffffff0000ULL;
304 3475187d bellard
                break;
305 3475187d bellard
            case 0x6: // 512k
306 3475187d bellard
                mask = 0xfffffffffff80000ULL;
307 3475187d bellard
                break;
308 3475187d bellard
            case 0x7: // 4M
309 3475187d bellard
                mask = 0xffffffffffc00000ULL;
310 3475187d bellard
                break;
311 3475187d bellard
            }
312 3475187d bellard
            // ctx match, vaddr match?
313 3475187d bellard
            if (env->immuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
314 3475187d bellard
                (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
315 3475187d bellard
                // access ok?
316 3475187d bellard
                if ((env->itlb_tte[i] & 0x4) && !(env->pstate & PS_PRIV)) {
317 3475187d bellard
                    env->exception_index = TT_TFAULT;
318 3475187d bellard
                    return 1;
319 3475187d bellard
                }
320 3475187d bellard
                *physical = env->itlb_tte[i] & 0xffffe000;
321 3475187d bellard
                *prot = PAGE_READ;
322 3475187d bellard
                return 0;
323 3475187d bellard
            }
324 3475187d bellard
        }
325 3475187d bellard
    }
326 3475187d bellard
    env->exception_index = TT_TFAULT;
327 3475187d bellard
    return 1;
328 3475187d bellard
}
329 3475187d bellard
330 3475187d bellard
int get_physical_address(CPUState *env, target_phys_addr_t *physical, int *prot,
331 3475187d bellard
                          int *access_index, target_ulong address, int rw,
332 3475187d bellard
                          int is_user)
333 3475187d bellard
{
334 3475187d bellard
    if (rw == 2)
335 3475187d bellard
        return get_physical_address_code(env, physical, prot, access_index, address, rw, is_user);
336 3475187d bellard
    else
337 3475187d bellard
        return get_physical_address_data(env, physical, prot, access_index, address, rw, is_user);
338 3475187d bellard
}
339 3475187d bellard
340 3475187d bellard
/* Perform address translation */
341 3475187d bellard
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
342 3475187d bellard
                              int is_user, int is_softmmu)
343 3475187d bellard
{
344 3475187d bellard
    target_ulong virt_addr;
345 3475187d bellard
    target_phys_addr_t paddr;
346 3475187d bellard
    unsigned long vaddr;
347 3475187d bellard
    int error_code = 0, prot, ret = 0, access_index;
348 3475187d bellard
349 3475187d bellard
    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
350 3475187d bellard
    if (error_code == 0) {
351 3475187d bellard
        virt_addr = address & TARGET_PAGE_MASK;
352 3475187d bellard
        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
353 3475187d bellard
        ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
354 3475187d bellard
        return ret;
355 3475187d bellard
    }
356 3475187d bellard
    // XXX
357 3475187d bellard
    return 1;
358 3475187d bellard
}
359 3475187d bellard
360 3475187d bellard
#endif
361 9d893301 bellard
#endif
362 e8af50a3 bellard
363 af7bf89b bellard
void memcpy32(target_ulong *dst, const target_ulong *src)
364 e8af50a3 bellard
{
365 e8af50a3 bellard
    dst[0] = src[0];
366 e8af50a3 bellard
    dst[1] = src[1];
367 e8af50a3 bellard
    dst[2] = src[2];
368 e8af50a3 bellard
    dst[3] = src[3];
369 e8af50a3 bellard
    dst[4] = src[4];
370 e8af50a3 bellard
    dst[5] = src[5];
371 e8af50a3 bellard
    dst[6] = src[6];
372 e8af50a3 bellard
    dst[7] = src[7];
373 e8af50a3 bellard
}
374 e8af50a3 bellard
375 ee5bbe38 bellard
#if !defined(TARGET_SPARC64)
376 ee5bbe38 bellard
target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
377 e80cfcfc bellard
{
378 e80cfcfc bellard
    target_phys_addr_t pde_ptr;
379 e80cfcfc bellard
    uint32_t pde;
380 e80cfcfc bellard
381 e80cfcfc bellard
    /* Context base + context number */
382 b3180cdc bellard
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
383 49be8030 bellard
    pde = ldl_phys(pde_ptr);
384 49be8030 bellard
385 e80cfcfc bellard
    switch (pde & PTE_ENTRYTYPE_MASK) {
386 e80cfcfc bellard
    default:
387 e80cfcfc bellard
    case 0: /* Invalid */
388 e80cfcfc bellard
    case 2: /* PTE, maybe should not happen? */
389 e80cfcfc bellard
    case 3: /* Reserved */
390 e80cfcfc bellard
        return 0;
391 e80cfcfc bellard
    case 1: /* L1 PDE */
392 e80cfcfc bellard
        if (mmulev == 3)
393 e80cfcfc bellard
            return pde;
394 e80cfcfc bellard
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
395 49be8030 bellard
        pde = ldl_phys(pde_ptr);
396 e80cfcfc bellard
397 e80cfcfc bellard
        switch (pde & PTE_ENTRYTYPE_MASK) {
398 e80cfcfc bellard
        default:
399 e80cfcfc bellard
        case 0: /* Invalid */
400 e80cfcfc bellard
        case 3: /* Reserved */
401 e80cfcfc bellard
            return 0;
402 e80cfcfc bellard
        case 2: /* L1 PTE */
403 e80cfcfc bellard
            return pde;
404 e80cfcfc bellard
        case 1: /* L2 PDE */
405 e80cfcfc bellard
            if (mmulev == 2)
406 e80cfcfc bellard
                return pde;
407 e80cfcfc bellard
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
408 49be8030 bellard
            pde = ldl_phys(pde_ptr);
409 e80cfcfc bellard
410 e80cfcfc bellard
            switch (pde & PTE_ENTRYTYPE_MASK) {
411 e80cfcfc bellard
            default:
412 e80cfcfc bellard
            case 0: /* Invalid */
413 e80cfcfc bellard
            case 3: /* Reserved */
414 e80cfcfc bellard
                return 0;
415 e80cfcfc bellard
            case 2: /* L2 PTE */
416 e80cfcfc bellard
                return pde;
417 e80cfcfc bellard
            case 1: /* L3 PDE */
418 e80cfcfc bellard
                if (mmulev == 1)
419 e80cfcfc bellard
                    return pde;
420 e80cfcfc bellard
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
421 49be8030 bellard
                pde = ldl_phys(pde_ptr);
422 e80cfcfc bellard
423 e80cfcfc bellard
                switch (pde & PTE_ENTRYTYPE_MASK) {
424 e80cfcfc bellard
                default:
425 e80cfcfc bellard
                case 0: /* Invalid */
426 e80cfcfc bellard
                case 1: /* PDE, should not happen */
427 e80cfcfc bellard
                case 3: /* Reserved */
428 e80cfcfc bellard
                    return 0;
429 e80cfcfc bellard
                case 2: /* L3 PTE */
430 e80cfcfc bellard
                    return pde;
431 e80cfcfc bellard
                }
432 e80cfcfc bellard
            }
433 e80cfcfc bellard
        }
434 e80cfcfc bellard
    }
435 e80cfcfc bellard
    return 0;
436 e80cfcfc bellard
}
437 e80cfcfc bellard
438 55754d9e bellard
#ifdef DEBUG_MMU
439 ee5bbe38 bellard
void dump_mmu(CPUState *env)
440 e80cfcfc bellard
{
441 af7bf89b bellard
     target_ulong va, va1, va2;
442 af7bf89b bellard
     unsigned int n, m, o;
443 af7bf89b bellard
     target_phys_addr_t pde_ptr, pa;
444 e80cfcfc bellard
    uint32_t pde;
445 e80cfcfc bellard
446 e80cfcfc bellard
    printf("MMU dump:\n");
447 b3180cdc bellard
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
448 49be8030 bellard
    pde = ldl_phys(pde_ptr);
449 af7bf89b bellard
    printf("Root ptr: " TARGET_FMT_lx ", ctx: %d\n", env->mmuregs[1] << 4, env->mmuregs[2]);
450 e80cfcfc bellard
    for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
451 ee5bbe38 bellard
        pde_ptr = mmu_probe(env, va, 2);
452 e80cfcfc bellard
        if (pde_ptr) {
453 e80cfcfc bellard
            pa = cpu_get_phys_page_debug(env, va);
454 af7bf89b bellard
             printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PDE: " TARGET_FMT_lx "\n", va, pa, pde_ptr);
455 e80cfcfc bellard
            for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
456 ee5bbe38 bellard
                pde_ptr = mmu_probe(env, va1, 1);
457 e80cfcfc bellard
                if (pde_ptr) {
458 e80cfcfc bellard
                    pa = cpu_get_phys_page_debug(env, va1);
459 af7bf89b bellard
                     printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PDE: " TARGET_FMT_lx "\n", va1, pa, pde_ptr);
460 e80cfcfc bellard
                    for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
461 ee5bbe38 bellard
                        pde_ptr = mmu_probe(env, va2, 0);
462 e80cfcfc bellard
                        if (pde_ptr) {
463 e80cfcfc bellard
                            pa = cpu_get_phys_page_debug(env, va2);
464 af7bf89b bellard
                             printf("  VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PTE: " TARGET_FMT_lx "\n", va2, pa, pde_ptr);
465 e80cfcfc bellard
                        }
466 e80cfcfc bellard
                    }
467 e80cfcfc bellard
                }
468 e80cfcfc bellard
            }
469 e80cfcfc bellard
        }
470 e80cfcfc bellard
    }
471 e80cfcfc bellard
    printf("MMU dump ends\n");
472 e80cfcfc bellard
}
473 55754d9e bellard
#endif
474 3475187d bellard
#endif