Statistics
| Branch: | Revision:

root / target-sparc / helper.c @ d3c61721

History | View | Annotate | Download (12.2 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 e8af50a3 bellard
#include "exec.h"
21 e8af50a3 bellard
22 e80cfcfc bellard
//#define DEBUG_PCALL
23 e80cfcfc bellard
//#define DEBUG_MMU
24 e8af50a3 bellard
25 e8af50a3 bellard
/* Sparc MMU emulation */
26 e8af50a3 bellard
int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
27 e8af50a3 bellard
                              int is_user, int is_softmmu);
28 e8af50a3 bellard
29 e8af50a3 bellard
/* thread support */
30 e8af50a3 bellard
31 e8af50a3 bellard
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
32 e8af50a3 bellard
33 e8af50a3 bellard
void cpu_lock(void)
34 e8af50a3 bellard
{
35 e8af50a3 bellard
    spin_lock(&global_cpu_lock);
36 e8af50a3 bellard
}
37 e8af50a3 bellard
38 e8af50a3 bellard
void cpu_unlock(void)
39 e8af50a3 bellard
{
40 e8af50a3 bellard
    spin_unlock(&global_cpu_lock);
41 e8af50a3 bellard
}
42 e8af50a3 bellard
43 e8af50a3 bellard
#if !defined(CONFIG_USER_ONLY) 
44 e8af50a3 bellard
45 e8af50a3 bellard
#define MMUSUFFIX _mmu
46 e8af50a3 bellard
#define GETPC() (__builtin_return_address(0))
47 e8af50a3 bellard
48 e8af50a3 bellard
#define SHIFT 0
49 e8af50a3 bellard
#include "softmmu_template.h"
50 e8af50a3 bellard
51 e8af50a3 bellard
#define SHIFT 1
52 e8af50a3 bellard
#include "softmmu_template.h"
53 e8af50a3 bellard
54 e8af50a3 bellard
#define SHIFT 2
55 e8af50a3 bellard
#include "softmmu_template.h"
56 e8af50a3 bellard
57 e8af50a3 bellard
#define SHIFT 3
58 e8af50a3 bellard
#include "softmmu_template.h"
59 e8af50a3 bellard
60 e8af50a3 bellard
61 e8af50a3 bellard
/* try to fill the TLB and return an exception if error. If retaddr is
62 e8af50a3 bellard
   NULL, it means that the function was called in C code (i.e. not
63 e8af50a3 bellard
   from generated code or from helper.c) */
64 e8af50a3 bellard
/* XXX: fix it to restore all registers */
65 0fa85d43 bellard
void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
66 e8af50a3 bellard
{
67 e8af50a3 bellard
    TranslationBlock *tb;
68 e8af50a3 bellard
    int ret;
69 e8af50a3 bellard
    unsigned long pc;
70 e8af50a3 bellard
    CPUState *saved_env;
71 e8af50a3 bellard
72 e8af50a3 bellard
    /* XXX: hack to restore env in all cases, even if not called from
73 e8af50a3 bellard
       generated code */
74 e8af50a3 bellard
    saved_env = env;
75 e8af50a3 bellard
    env = cpu_single_env;
76 e8af50a3 bellard
77 e8af50a3 bellard
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
78 e8af50a3 bellard
    if (ret) {
79 e8af50a3 bellard
        if (retaddr) {
80 e8af50a3 bellard
            /* now we have a real cpu fault */
81 e8af50a3 bellard
            pc = (unsigned long)retaddr;
82 e8af50a3 bellard
            tb = tb_find_pc(pc);
83 e8af50a3 bellard
            if (tb) {
84 e8af50a3 bellard
                /* the PC is inside the translated code. It means that we have
85 e8af50a3 bellard
                   a virtual CPU fault */
86 e8af50a3 bellard
                cpu_restore_state(tb, env, pc, NULL);
87 e8af50a3 bellard
            }
88 e8af50a3 bellard
        }
89 e8af50a3 bellard
        raise_exception_err(ret, env->error_code);
90 e8af50a3 bellard
    }
91 e8af50a3 bellard
    env = saved_env;
92 e8af50a3 bellard
}
93 e8af50a3 bellard
#endif
94 e8af50a3 bellard
95 e8af50a3 bellard
static const int access_table[8][8] = {
96 e8af50a3 bellard
    { 0, 0, 0, 0, 2, 0, 3, 3 },
97 e8af50a3 bellard
    { 0, 0, 0, 0, 2, 0, 0, 0 },
98 e8af50a3 bellard
    { 2, 2, 0, 0, 0, 2, 3, 3 },
99 e8af50a3 bellard
    { 2, 2, 0, 0, 0, 2, 0, 0 },
100 e8af50a3 bellard
    { 2, 0, 2, 0, 2, 2, 3, 3 },
101 e8af50a3 bellard
    { 2, 0, 2, 0, 2, 0, 2, 0 },
102 e8af50a3 bellard
    { 2, 2, 2, 0, 2, 2, 3, 3 },
103 e8af50a3 bellard
    { 2, 2, 2, 0, 2, 2, 2, 0 }
104 e8af50a3 bellard
};
105 e8af50a3 bellard
106 e8af50a3 bellard
/* 1 = write OK */
107 e8af50a3 bellard
static const int rw_table[2][8] = {
108 e8af50a3 bellard
    { 0, 1, 0, 1, 0, 1, 0, 1 },
109 e8af50a3 bellard
    { 0, 1, 0, 1, 0, 0, 0, 0 }
110 e8af50a3 bellard
};
111 e8af50a3 bellard
112 e80cfcfc bellard
int get_physical_address (CPUState *env, uint32_t *physical, int *prot,
113 e80cfcfc bellard
                          int *access_index, uint32_t address, int rw,
114 e80cfcfc bellard
                          int is_user)
115 e8af50a3 bellard
{
116 e80cfcfc bellard
    int access_perms = 0;
117 e80cfcfc bellard
    target_phys_addr_t pde_ptr;
118 e8af50a3 bellard
    uint32_t pde, virt_addr;
119 e80cfcfc bellard
    int error_code = 0, is_dirty;
120 e80cfcfc bellard
    unsigned long page_offset;
121 e8af50a3 bellard
122 e8af50a3 bellard
    virt_addr = address & TARGET_PAGE_MASK;
123 e8af50a3 bellard
    if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
124 e80cfcfc bellard
        *physical = address;
125 e80cfcfc bellard
        *prot = PAGE_READ | PAGE_WRITE;
126 e80cfcfc bellard
        return 0;
127 e8af50a3 bellard
    }
128 e8af50a3 bellard
129 e8af50a3 bellard
    /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
130 e8af50a3 bellard
    /* Context base + context number */
131 e80cfcfc bellard
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
132 e80cfcfc bellard
    cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
133 e80cfcfc bellard
    bswap32s(&pde);
134 e8af50a3 bellard
135 e8af50a3 bellard
    /* Ctx pde */
136 e8af50a3 bellard
    switch (pde & PTE_ENTRYTYPE_MASK) {
137 e80cfcfc bellard
    default:
138 e8af50a3 bellard
    case 0: /* Invalid */
139 e80cfcfc bellard
        return 1;
140 e80cfcfc bellard
    case 2: /* L0 PTE, maybe should not happen? */
141 e8af50a3 bellard
    case 3: /* Reserved */
142 e80cfcfc bellard
        return 4;
143 e80cfcfc bellard
    case 1: /* L0 PDE */
144 e80cfcfc bellard
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
145 e80cfcfc bellard
        cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
146 e80cfcfc bellard
        bswap32s(&pde);
147 e8af50a3 bellard
148 e8af50a3 bellard
        switch (pde & PTE_ENTRYTYPE_MASK) {
149 e80cfcfc bellard
        default:
150 e8af50a3 bellard
        case 0: /* Invalid */
151 e80cfcfc bellard
            return 1;
152 e8af50a3 bellard
        case 3: /* Reserved */
153 e80cfcfc bellard
            return 4;
154 e80cfcfc bellard
        case 1: /* L1 PDE */
155 e80cfcfc bellard
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
156 e80cfcfc bellard
            cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
157 e80cfcfc bellard
            bswap32s(&pde);
158 e8af50a3 bellard
159 e8af50a3 bellard
            switch (pde & PTE_ENTRYTYPE_MASK) {
160 e80cfcfc bellard
            default:
161 e8af50a3 bellard
            case 0: /* Invalid */
162 e80cfcfc bellard
                return 1;
163 e8af50a3 bellard
            case 3: /* Reserved */
164 e80cfcfc bellard
                return 4;
165 e80cfcfc bellard
            case 1: /* L2 PDE */
166 e80cfcfc bellard
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
167 e80cfcfc bellard
                cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
168 e80cfcfc bellard
                bswap32s(&pde);
169 e8af50a3 bellard
170 e8af50a3 bellard
                switch (pde & PTE_ENTRYTYPE_MASK) {
171 e80cfcfc bellard
                default:
172 e8af50a3 bellard
                case 0: /* Invalid */
173 e80cfcfc bellard
                    return 1;
174 e8af50a3 bellard
                case 1: /* PDE, should not happen */
175 e8af50a3 bellard
                case 3: /* Reserved */
176 e80cfcfc bellard
                    return 4;
177 e8af50a3 bellard
                case 2: /* L3 PTE */
178 e8af50a3 bellard
                    virt_addr = address & TARGET_PAGE_MASK;
179 e8af50a3 bellard
                    page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1);
180 e8af50a3 bellard
                }
181 e8af50a3 bellard
                break;
182 e8af50a3 bellard
            case 2: /* L2 PTE */
183 e8af50a3 bellard
                virt_addr = address & ~0x3ffff;
184 e8af50a3 bellard
                page_offset = address & 0x3ffff;
185 e8af50a3 bellard
            }
186 e8af50a3 bellard
            break;
187 e8af50a3 bellard
        case 2: /* L1 PTE */
188 e8af50a3 bellard
            virt_addr = address & ~0xffffff;
189 e8af50a3 bellard
            page_offset = address & 0xffffff;
190 e8af50a3 bellard
        }
191 e8af50a3 bellard
    }
192 e8af50a3 bellard
193 e8af50a3 bellard
    /* update page modified and dirty bits */
194 b769d8fe bellard
    is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
195 e8af50a3 bellard
    if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
196 e80cfcfc bellard
        uint32_t tmppde;
197 e8af50a3 bellard
        pde |= PG_ACCESSED_MASK;
198 e8af50a3 bellard
        if (is_dirty)
199 e8af50a3 bellard
            pde |= PG_MODIFIED_MASK;
200 e80cfcfc bellard
        tmppde = bswap32(pde);
201 e80cfcfc bellard
        cpu_physical_memory_write(pde_ptr, (uint8_t *)&tmppde, 4);
202 e8af50a3 bellard
    }
203 e8af50a3 bellard
    /* check access */
204 e80cfcfc bellard
    *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
205 e8af50a3 bellard
    access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
206 e80cfcfc bellard
    error_code = access_table[*access_index][access_perms];
207 e8af50a3 bellard
    if (error_code)
208 e80cfcfc bellard
        return error_code;
209 e8af50a3 bellard
210 e8af50a3 bellard
    /* the page can be put in the TLB */
211 e80cfcfc bellard
    *prot = PAGE_READ;
212 e8af50a3 bellard
    if (pde & PG_MODIFIED_MASK) {
213 e8af50a3 bellard
        /* only set write access if already dirty... otherwise wait
214 e8af50a3 bellard
           for dirty access */
215 e8af50a3 bellard
        if (rw_table[is_user][access_perms])
216 e80cfcfc bellard
                *prot |= PAGE_WRITE;
217 e8af50a3 bellard
    }
218 e8af50a3 bellard
219 e8af50a3 bellard
    /* Even if large ptes, we map only one 4KB page in the cache to
220 e8af50a3 bellard
       avoid filling it too fast */
221 e80cfcfc bellard
    *physical = ((pde & PTE_ADDR_MASK) << 4) + page_offset;
222 e80cfcfc bellard
    return 0;
223 e80cfcfc bellard
}
224 e80cfcfc bellard
225 e80cfcfc bellard
/* Perform address translation */
226 e80cfcfc bellard
int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
227 e80cfcfc bellard
                              int is_user, int is_softmmu)
228 e80cfcfc bellard
{
229 e80cfcfc bellard
    int exception = 0;
230 e80cfcfc bellard
    uint32_t virt_addr, paddr;
231 e80cfcfc bellard
    unsigned long vaddr;
232 e80cfcfc bellard
    int error_code = 0, prot, ret = 0, access_index;
233 e8af50a3 bellard
234 e80cfcfc bellard
    if (env->user_mode_only) {
235 e80cfcfc bellard
        /* user mode only emulation */
236 e80cfcfc bellard
        error_code = -2;
237 e80cfcfc bellard
        goto do_fault_user;
238 e80cfcfc bellard
    }
239 e8af50a3 bellard
240 e80cfcfc bellard
    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
241 e80cfcfc bellard
    if (error_code == 0) {
242 e80cfcfc bellard
        virt_addr = address & TARGET_PAGE_MASK;
243 e80cfcfc bellard
        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
244 e80cfcfc bellard
        ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
245 e80cfcfc bellard
        return ret;
246 e80cfcfc bellard
    }
247 e8af50a3 bellard
248 e8af50a3 bellard
    if (env->mmuregs[3]) /* Fault status register */
249 e8af50a3 bellard
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
250 e8af50a3 bellard
    env->mmuregs[3] |= (access_index << 5) | (error_code << 2) | 2;
251 e8af50a3 bellard
    env->mmuregs[4] = address; /* Fault address register */
252 e8af50a3 bellard
253 8d5f07fa bellard
    if (env->mmuregs[0] & MMU_NF || env->psret == 0) // No fault
254 e8af50a3 bellard
        return 0;
255 e80cfcfc bellard
 do_fault_user:
256 e8af50a3 bellard
    env->exception_index = exception;
257 e8af50a3 bellard
    env->error_code = error_code;
258 e8af50a3 bellard
    return error_code;
259 e8af50a3 bellard
}
260 e8af50a3 bellard
261 e8af50a3 bellard
void memcpy32(uint32_t *dst, const uint32_t *src)
262 e8af50a3 bellard
{
263 e8af50a3 bellard
    dst[0] = src[0];
264 e8af50a3 bellard
    dst[1] = src[1];
265 e8af50a3 bellard
    dst[2] = src[2];
266 e8af50a3 bellard
    dst[3] = src[3];
267 e8af50a3 bellard
    dst[4] = src[4];
268 e8af50a3 bellard
    dst[5] = src[5];
269 e8af50a3 bellard
    dst[6] = src[6];
270 e8af50a3 bellard
    dst[7] = src[7];
271 e8af50a3 bellard
}
272 e8af50a3 bellard
273 e8af50a3 bellard
void set_cwp(int new_cwp)
274 e8af50a3 bellard
{
275 e8af50a3 bellard
    /* put the modified wrap registers at their proper location */
276 e8af50a3 bellard
    if (env->cwp == (NWINDOWS - 1))
277 e8af50a3 bellard
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
278 e8af50a3 bellard
    env->cwp = new_cwp;
279 e8af50a3 bellard
    /* put the wrap registers at their temporary location */
280 e8af50a3 bellard
    if (new_cwp == (NWINDOWS - 1))
281 e8af50a3 bellard
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
282 e8af50a3 bellard
    env->regwptr = env->regbase + (new_cwp * 16);
283 e8af50a3 bellard
}
284 e8af50a3 bellard
285 0fa85d43 bellard
void cpu_set_cwp(CPUState *env1, int new_cwp)
286 0fa85d43 bellard
{
287 0fa85d43 bellard
    CPUState *saved_env;
288 0fa85d43 bellard
    saved_env = env;
289 0fa85d43 bellard
    env = env1;
290 0fa85d43 bellard
    set_cwp(new_cwp);
291 0fa85d43 bellard
    env = saved_env;
292 0fa85d43 bellard
}
293 0fa85d43 bellard
294 e8af50a3 bellard
/*
295 e8af50a3 bellard
 * Begin execution of an interruption. is_int is TRUE if coming from
296 e8af50a3 bellard
 * the int instruction. next_eip is the EIP value AFTER the interrupt
297 e8af50a3 bellard
 * instruction. It is only relevant if is_int is TRUE.  
298 e8af50a3 bellard
 */
299 e8af50a3 bellard
void do_interrupt(int intno, int is_int, int error_code, 
300 e8af50a3 bellard
                  unsigned int next_eip, int is_hw)
301 e8af50a3 bellard
{
302 e8af50a3 bellard
    int cwp;
303 e8af50a3 bellard
304 e8af50a3 bellard
#ifdef DEBUG_PCALL
305 e8af50a3 bellard
    if (loglevel & CPU_LOG_INT) {
306 e8af50a3 bellard
        static int count;
307 e8af50a3 bellard
        fprintf(logfile, "%6d: v=%02x e=%04x i=%d pc=%08x npc=%08x SP=%08x\n",
308 e8af50a3 bellard
                    count, intno, error_code, is_int,
309 e8af50a3 bellard
                    env->pc,
310 8d5f07fa bellard
                    env->npc, env->regwptr[6]);
311 e80cfcfc bellard
#if 1
312 7fe48483 bellard
        cpu_dump_state(env, logfile, fprintf, 0);
313 e8af50a3 bellard
        {
314 e8af50a3 bellard
            int i;
315 e8af50a3 bellard
            uint8_t *ptr;
316 e80cfcfc bellard
317 e8af50a3 bellard
            fprintf(logfile, "       code=");
318 e80cfcfc bellard
            ptr = (uint8_t *)env->pc;
319 e8af50a3 bellard
            for(i = 0; i < 16; i++) {
320 e8af50a3 bellard
                fprintf(logfile, " %02x", ldub(ptr + i));
321 e8af50a3 bellard
            }
322 e8af50a3 bellard
            fprintf(logfile, "\n");
323 e8af50a3 bellard
        }
324 e8af50a3 bellard
#endif
325 e8af50a3 bellard
        count++;
326 e8af50a3 bellard
    }
327 e8af50a3 bellard
#endif
328 e80cfcfc bellard
#if !defined(CONFIG_USER_ONLY) 
329 e80cfcfc bellard
    if (env->psret == 0) {
330 0fa85d43 bellard
        cpu_abort(cpu_single_env, "Trap while interrupts disabled, Error state");
331 e80cfcfc bellard
        return;
332 e80cfcfc bellard
    }
333 e80cfcfc bellard
#endif
334 e8af50a3 bellard
    env->psret = 0;
335 e8af50a3 bellard
    cwp = (env->cwp - 1) & (NWINDOWS - 1); 
336 e8af50a3 bellard
    set_cwp(cwp);
337 e80cfcfc bellard
    env->regwptr[9] = env->pc - 4; // XXX?
338 e80cfcfc bellard
    env->regwptr[10] = env->pc;
339 e8af50a3 bellard
    env->psrps = env->psrs;
340 e8af50a3 bellard
    env->psrs = 1;
341 e8af50a3 bellard
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
342 e8af50a3 bellard
    env->pc = env->tbr;
343 e8af50a3 bellard
    env->npc = env->pc + 4;
344 e8af50a3 bellard
    env->exception_index = 0;
345 e8af50a3 bellard
}
346 e8af50a3 bellard
347 e8af50a3 bellard
void raise_exception_err(int exception_index, int error_code)
348 e8af50a3 bellard
{
349 e8af50a3 bellard
    raise_exception(exception_index);
350 e8af50a3 bellard
}
351 e80cfcfc bellard
352 e80cfcfc bellard
uint32_t mmu_probe(uint32_t address, int mmulev)
353 e80cfcfc bellard
{
354 e80cfcfc bellard
    target_phys_addr_t pde_ptr;
355 e80cfcfc bellard
    uint32_t pde;
356 e80cfcfc bellard
357 e80cfcfc bellard
    /* Context base + context number */
358 e80cfcfc bellard
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
359 e80cfcfc bellard
    cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
360 e80cfcfc bellard
    bswap32s(&pde);
361 e80cfcfc bellard
    switch (pde & PTE_ENTRYTYPE_MASK) {
362 e80cfcfc bellard
    default:
363 e80cfcfc bellard
    case 0: /* Invalid */
364 e80cfcfc bellard
    case 2: /* PTE, maybe should not happen? */
365 e80cfcfc bellard
    case 3: /* Reserved */
366 e80cfcfc bellard
        return 0;
367 e80cfcfc bellard
    case 1: /* L1 PDE */
368 e80cfcfc bellard
        if (mmulev == 3)
369 e80cfcfc bellard
            return pde;
370 e80cfcfc bellard
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
371 e80cfcfc bellard
        cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
372 e80cfcfc bellard
        bswap32s(&pde);
373 e80cfcfc bellard
374 e80cfcfc bellard
        switch (pde & PTE_ENTRYTYPE_MASK) {
375 e80cfcfc bellard
        default:
376 e80cfcfc bellard
        case 0: /* Invalid */
377 e80cfcfc bellard
        case 3: /* Reserved */
378 e80cfcfc bellard
            return 0;
379 e80cfcfc bellard
        case 2: /* L1 PTE */
380 e80cfcfc bellard
            return pde;
381 e80cfcfc bellard
        case 1: /* L2 PDE */
382 e80cfcfc bellard
            if (mmulev == 2)
383 e80cfcfc bellard
                return pde;
384 e80cfcfc bellard
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
385 e80cfcfc bellard
            cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
386 e80cfcfc bellard
            bswap32s(&pde);
387 e80cfcfc bellard
388 e80cfcfc bellard
            switch (pde & PTE_ENTRYTYPE_MASK) {
389 e80cfcfc bellard
            default:
390 e80cfcfc bellard
            case 0: /* Invalid */
391 e80cfcfc bellard
            case 3: /* Reserved */
392 e80cfcfc bellard
                return 0;
393 e80cfcfc bellard
            case 2: /* L2 PTE */
394 e80cfcfc bellard
                return pde;
395 e80cfcfc bellard
            case 1: /* L3 PDE */
396 e80cfcfc bellard
                if (mmulev == 1)
397 e80cfcfc bellard
                    return pde;
398 e80cfcfc bellard
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
399 e80cfcfc bellard
                cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
400 e80cfcfc bellard
                bswap32s(&pde);
401 e80cfcfc bellard
402 e80cfcfc bellard
                switch (pde & PTE_ENTRYTYPE_MASK) {
403 e80cfcfc bellard
                default:
404 e80cfcfc bellard
                case 0: /* Invalid */
405 e80cfcfc bellard
                case 1: /* PDE, should not happen */
406 e80cfcfc bellard
                case 3: /* Reserved */
407 e80cfcfc bellard
                    return 0;
408 e80cfcfc bellard
                case 2: /* L3 PTE */
409 e80cfcfc bellard
                    return pde;
410 e80cfcfc bellard
                }
411 e80cfcfc bellard
            }
412 e80cfcfc bellard
        }
413 e80cfcfc bellard
    }
414 e80cfcfc bellard
    return 0;
415 e80cfcfc bellard
}
416 e80cfcfc bellard
417 e80cfcfc bellard
void dump_mmu(void)
418 e80cfcfc bellard
{
419 e80cfcfc bellard
#ifdef DEBUG_MMU
420 e80cfcfc bellard
    uint32_t pa, va, va1, va2;
421 e80cfcfc bellard
    int n, m, o;
422 e80cfcfc bellard
    target_phys_addr_t pde_ptr;
423 e80cfcfc bellard
    uint32_t pde;
424 e80cfcfc bellard
425 e80cfcfc bellard
    printf("MMU dump:\n");
426 e80cfcfc bellard
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
427 e80cfcfc bellard
    cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
428 e80cfcfc bellard
    bswap32s(&pde);
429 e80cfcfc bellard
    printf("Root ptr: 0x%08x, ctx: %d\n", env->mmuregs[1] << 4, env->mmuregs[2]);
430 e80cfcfc bellard
    for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
431 e80cfcfc bellard
        pde_ptr = mmu_probe(va, 2);
432 e80cfcfc bellard
        if (pde_ptr) {
433 e80cfcfc bellard
            pa = cpu_get_phys_page_debug(env, va);
434 e80cfcfc bellard
            printf("VA: 0x%08x, PA: 0x%08x PDE: 0x%08x\n", va, pa, pde_ptr);
435 e80cfcfc bellard
            for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
436 e80cfcfc bellard
                pde_ptr = mmu_probe(va1, 1);
437 e80cfcfc bellard
                if (pde_ptr) {
438 e80cfcfc bellard
                    pa = cpu_get_phys_page_debug(env, va1);
439 e80cfcfc bellard
                    printf(" VA: 0x%08x, PA: 0x%08x PDE: 0x%08x\n", va1, pa, pde_ptr);
440 e80cfcfc bellard
                    for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
441 e80cfcfc bellard
                        pde_ptr = mmu_probe(va2, 0);
442 e80cfcfc bellard
                        if (pde_ptr) {
443 e80cfcfc bellard
                            pa = cpu_get_phys_page_debug(env, va2);
444 e80cfcfc bellard
                            printf("  VA: 0x%08x, PA: 0x%08x PTE: 0x%08x\n", va2, pa, pde_ptr);
445 e80cfcfc bellard
                        }
446 e80cfcfc bellard
                    }
447 e80cfcfc bellard
                }
448 e80cfcfc bellard
            }
449 e80cfcfc bellard
        }
450 e80cfcfc bellard
    }
451 e80cfcfc bellard
    printf("MMU dump ends\n");
452 e80cfcfc bellard
#endif
453 e80cfcfc bellard
}