Statistics
| Branch: | Revision:

root / target-sparc / helper.c @ f68c781c

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

463 3475187d bellard
            fprintf(logfile, "       code=");
464 3475187d bellard
            ptr = (uint8_t *)env->pc;
465 3475187d bellard
            for(i = 0; i < 16; i++) {
466 3475187d bellard
                fprintf(logfile, " %02x", ldub(ptr + i));
467 3475187d bellard
            }
468 3475187d bellard
            fprintf(logfile, "\n");
469 3475187d bellard
        }
470 3475187d bellard
#endif
471 3475187d bellard
        count++;
472 3475187d bellard
    }
473 3475187d bellard
#endif
474 3475187d bellard
#if !defined(CONFIG_USER_ONLY) 
475 3475187d bellard
    if (env->pstate & PS_IE) {
476 3475187d bellard
        cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
477 3475187d bellard
        return;
478 3475187d bellard
    }
479 3475187d bellard
#endif
480 3475187d bellard
    env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
481 3475187d bellard
        ((env->pstate & 0xfff) << 8) | (env->cwp & 0xff);
482 3475187d bellard
    env->tpc[env->tl] = env->pc;
483 3475187d bellard
    env->tnpc[env->tl] = env->npc;
484 3475187d bellard
    env->tt[env->tl] = intno;
485 3475187d bellard
    env->tbr = env->tbr | (env->tl > 1) ? 1 << 14 : 0 | (intno << 4);
486 3475187d bellard
    env->tl++;
487 3475187d bellard
    env->pc = env->tbr;
488 3475187d bellard
    env->npc = env->pc + 4;
489 3475187d bellard
    env->exception_index = 0;
490 3475187d bellard
}
491 3475187d bellard
#else
492 878d3096 bellard
void do_interrupt(int intno)
493 e8af50a3 bellard
{
494 e8af50a3 bellard
    int cwp;
495 e8af50a3 bellard
496 e8af50a3 bellard
#ifdef DEBUG_PCALL
497 e8af50a3 bellard
    if (loglevel & CPU_LOG_INT) {
498 e8af50a3 bellard
        static int count;
499 878d3096 bellard
        fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
500 878d3096 bellard
                count, intno,
501 9d893301 bellard
                env->pc,
502 9d893301 bellard
                env->npc, env->regwptr[6]);
503 7fe48483 bellard
        cpu_dump_state(env, logfile, fprintf, 0);
504 6f7e9aec bellard
#if 0
505 e8af50a3 bellard
        {
506 e8af50a3 bellard
            int i;
507 e8af50a3 bellard
            uint8_t *ptr;
508 e80cfcfc bellard

509 e8af50a3 bellard
            fprintf(logfile, "       code=");
510 e80cfcfc bellard
            ptr = (uint8_t *)env->pc;
511 e8af50a3 bellard
            for(i = 0; i < 16; i++) {
512 e8af50a3 bellard
                fprintf(logfile, " %02x", ldub(ptr + i));
513 e8af50a3 bellard
            }
514 e8af50a3 bellard
            fprintf(logfile, "\n");
515 e8af50a3 bellard
        }
516 e8af50a3 bellard
#endif
517 e8af50a3 bellard
        count++;
518 e8af50a3 bellard
    }
519 e8af50a3 bellard
#endif
520 e80cfcfc bellard
#if !defined(CONFIG_USER_ONLY) 
521 e80cfcfc bellard
    if (env->psret == 0) {
522 878d3096 bellard
        cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
523 e80cfcfc bellard
        return;
524 e80cfcfc bellard
    }
525 e80cfcfc bellard
#endif
526 e8af50a3 bellard
    env->psret = 0;
527 e8af50a3 bellard
    cwp = (env->cwp - 1) & (NWINDOWS - 1); 
528 e8af50a3 bellard
    set_cwp(cwp);
529 878d3096 bellard
    env->regwptr[9] = env->pc;
530 878d3096 bellard
    env->regwptr[10] = env->npc;
531 e8af50a3 bellard
    env->psrps = env->psrs;
532 e8af50a3 bellard
    env->psrs = 1;
533 e8af50a3 bellard
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
534 e8af50a3 bellard
    env->pc = env->tbr;
535 e8af50a3 bellard
    env->npc = env->pc + 4;
536 e8af50a3 bellard
    env->exception_index = 0;
537 e8af50a3 bellard
}
538 e8af50a3 bellard
539 af7bf89b bellard
target_ulong mmu_probe(target_ulong address, int mmulev)
540 e80cfcfc bellard
{
541 e80cfcfc bellard
    target_phys_addr_t pde_ptr;
542 e80cfcfc bellard
    uint32_t pde;
543 e80cfcfc bellard
544 e80cfcfc bellard
    /* Context base + context number */
545 b3180cdc bellard
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
546 49be8030 bellard
    pde = ldl_phys(pde_ptr);
547 49be8030 bellard
548 e80cfcfc bellard
    switch (pde & PTE_ENTRYTYPE_MASK) {
549 e80cfcfc bellard
    default:
550 e80cfcfc bellard
    case 0: /* Invalid */
551 e80cfcfc bellard
    case 2: /* PTE, maybe should not happen? */
552 e80cfcfc bellard
    case 3: /* Reserved */
553 e80cfcfc bellard
        return 0;
554 e80cfcfc bellard
    case 1: /* L1 PDE */
555 e80cfcfc bellard
        if (mmulev == 3)
556 e80cfcfc bellard
            return pde;
557 e80cfcfc bellard
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
558 49be8030 bellard
        pde = ldl_phys(pde_ptr);
559 e80cfcfc bellard
560 e80cfcfc bellard
        switch (pde & PTE_ENTRYTYPE_MASK) {
561 e80cfcfc bellard
        default:
562 e80cfcfc bellard
        case 0: /* Invalid */
563 e80cfcfc bellard
        case 3: /* Reserved */
564 e80cfcfc bellard
            return 0;
565 e80cfcfc bellard
        case 2: /* L1 PTE */
566 e80cfcfc bellard
            return pde;
567 e80cfcfc bellard
        case 1: /* L2 PDE */
568 e80cfcfc bellard
            if (mmulev == 2)
569 e80cfcfc bellard
                return pde;
570 e80cfcfc bellard
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
571 49be8030 bellard
            pde = ldl_phys(pde_ptr);
572 e80cfcfc bellard
573 e80cfcfc bellard
            switch (pde & PTE_ENTRYTYPE_MASK) {
574 e80cfcfc bellard
            default:
575 e80cfcfc bellard
            case 0: /* Invalid */
576 e80cfcfc bellard
            case 3: /* Reserved */
577 e80cfcfc bellard
                return 0;
578 e80cfcfc bellard
            case 2: /* L2 PTE */
579 e80cfcfc bellard
                return pde;
580 e80cfcfc bellard
            case 1: /* L3 PDE */
581 e80cfcfc bellard
                if (mmulev == 1)
582 e80cfcfc bellard
                    return pde;
583 e80cfcfc bellard
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
584 49be8030 bellard
                pde = ldl_phys(pde_ptr);
585 e80cfcfc bellard
586 e80cfcfc bellard
                switch (pde & PTE_ENTRYTYPE_MASK) {
587 e80cfcfc bellard
                default:
588 e80cfcfc bellard
                case 0: /* Invalid */
589 e80cfcfc bellard
                case 1: /* PDE, should not happen */
590 e80cfcfc bellard
                case 3: /* Reserved */
591 e80cfcfc bellard
                    return 0;
592 e80cfcfc bellard
                case 2: /* L3 PTE */
593 e80cfcfc bellard
                    return pde;
594 e80cfcfc bellard
                }
595 e80cfcfc bellard
            }
596 e80cfcfc bellard
        }
597 e80cfcfc bellard
    }
598 e80cfcfc bellard
    return 0;
599 e80cfcfc bellard
}
600 e80cfcfc bellard
601 55754d9e bellard
#ifdef DEBUG_MMU
602 e80cfcfc bellard
void dump_mmu(void)
603 e80cfcfc bellard
{
604 af7bf89b bellard
     target_ulong va, va1, va2;
605 af7bf89b bellard
     unsigned int n, m, o;
606 af7bf89b bellard
     target_phys_addr_t pde_ptr, pa;
607 e80cfcfc bellard
    uint32_t pde;
608 e80cfcfc bellard
609 e80cfcfc bellard
    printf("MMU dump:\n");
610 b3180cdc bellard
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
611 49be8030 bellard
    pde = ldl_phys(pde_ptr);
612 af7bf89b bellard
    printf("Root ptr: " TARGET_FMT_lx ", ctx: %d\n", env->mmuregs[1] << 4, env->mmuregs[2]);
613 e80cfcfc bellard
    for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
614 e80cfcfc bellard
        pde_ptr = mmu_probe(va, 2);
615 e80cfcfc bellard
        if (pde_ptr) {
616 e80cfcfc bellard
            pa = cpu_get_phys_page_debug(env, va);
617 af7bf89b bellard
             printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PDE: " TARGET_FMT_lx "\n", va, pa, pde_ptr);
618 e80cfcfc bellard
            for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
619 e80cfcfc bellard
                pde_ptr = mmu_probe(va1, 1);
620 e80cfcfc bellard
                if (pde_ptr) {
621 e80cfcfc bellard
                    pa = cpu_get_phys_page_debug(env, va1);
622 af7bf89b bellard
                     printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PDE: " TARGET_FMT_lx "\n", va1, pa, pde_ptr);
623 e80cfcfc bellard
                    for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
624 e80cfcfc bellard
                        pde_ptr = mmu_probe(va2, 0);
625 e80cfcfc bellard
                        if (pde_ptr) {
626 e80cfcfc bellard
                            pa = cpu_get_phys_page_debug(env, va2);
627 af7bf89b bellard
                             printf("  VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PTE: " TARGET_FMT_lx "\n", va2, pa, pde_ptr);
628 e80cfcfc bellard
                        }
629 e80cfcfc bellard
                    }
630 e80cfcfc bellard
                }
631 e80cfcfc bellard
            }
632 e80cfcfc bellard
        }
633 e80cfcfc bellard
    }
634 e80cfcfc bellard
    printf("MMU dump ends\n");
635 e80cfcfc bellard
}
636 55754d9e bellard
#endif
637 3475187d bellard
#endif