Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ 3ab493de

History | View | Annotate | Download (12.5 kB)

1 2c0262af bellard
/*
2 2c0262af bellard
 *  i386 helpers (without register variable usage)
3 2c0262af bellard
 * 
4 2c0262af bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 2c0262af bellard
 *
6 2c0262af bellard
 * This library is free software; you can redistribute it and/or
7 2c0262af bellard
 * modify it under the terms of the GNU Lesser General Public
8 2c0262af bellard
 * License as published by the Free Software Foundation; either
9 2c0262af bellard
 * version 2 of the License, or (at your option) any later version.
10 2c0262af bellard
 *
11 2c0262af bellard
 * This library is distributed in the hope that it will be useful,
12 2c0262af bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 2c0262af bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 2c0262af bellard
 * Lesser General Public License for more details.
15 2c0262af bellard
 *
16 2c0262af bellard
 * You should have received a copy of the GNU Lesser General Public
17 2c0262af bellard
 * License along with this library; if not, write to the Free Software
18 2c0262af bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 2c0262af bellard
 */
20 2c0262af bellard
#include <stdarg.h>
21 2c0262af bellard
#include <stdlib.h>
22 2c0262af bellard
#include <stdio.h>
23 2c0262af bellard
#include <string.h>
24 2c0262af bellard
#include <inttypes.h>
25 2c0262af bellard
#include <signal.h>
26 2c0262af bellard
#include <assert.h>
27 2c0262af bellard
#include <sys/mman.h>
28 2c0262af bellard
29 2c0262af bellard
#include "cpu.h"
30 2c0262af bellard
#include "exec-all.h"
31 2c0262af bellard
32 2c0262af bellard
//#define DEBUG_MMU
33 2c0262af bellard
34 2c0262af bellard
CPUX86State *cpu_x86_init(void)
35 2c0262af bellard
{
36 2c0262af bellard
    CPUX86State *env;
37 2c0262af bellard
    int i;
38 2c0262af bellard
    static int inited;
39 2c0262af bellard
40 2c0262af bellard
    cpu_exec_init();
41 2c0262af bellard
42 2c0262af bellard
    env = malloc(sizeof(CPUX86State));
43 2c0262af bellard
    if (!env)
44 2c0262af bellard
        return NULL;
45 2c0262af bellard
    memset(env, 0, sizeof(CPUX86State));
46 2c0262af bellard
    /* basic FPU init */
47 2c0262af bellard
    for(i = 0;i < 8; i++)
48 2c0262af bellard
        env->fptags[i] = 1;
49 2c0262af bellard
    env->fpuc = 0x37f;
50 2c0262af bellard
    /* flags setup : we activate the IRQs by default as in user mode */
51 2c0262af bellard
    env->eflags = 0x2 | IF_MASK;
52 2c0262af bellard
53 2c0262af bellard
    tlb_flush(env);
54 2c0262af bellard
#ifdef CONFIG_SOFTMMU
55 2c0262af bellard
    env->hflags |= HF_SOFTMMU_MASK;
56 2c0262af bellard
#endif
57 2c0262af bellard
    /* init various static tables */
58 2c0262af bellard
    if (!inited) {
59 2c0262af bellard
        inited = 1;
60 2c0262af bellard
        optimize_flags_init();
61 2c0262af bellard
    }
62 2c0262af bellard
    return env;
63 2c0262af bellard
}
64 2c0262af bellard
65 2c0262af bellard
void cpu_x86_close(CPUX86State *env)
66 2c0262af bellard
{
67 2c0262af bellard
    free(env);
68 2c0262af bellard
}
69 2c0262af bellard
70 2c0262af bellard
/***********************************************************/
71 2c0262af bellard
/* x86 debug */
72 2c0262af bellard
73 2c0262af bellard
static const char *cc_op_str[] = {
74 2c0262af bellard
    "DYNAMIC",
75 2c0262af bellard
    "EFLAGS",
76 2c0262af bellard
    "MUL",
77 2c0262af bellard
    "ADDB",
78 2c0262af bellard
    "ADDW",
79 2c0262af bellard
    "ADDL",
80 2c0262af bellard
    "ADCB",
81 2c0262af bellard
    "ADCW",
82 2c0262af bellard
    "ADCL",
83 2c0262af bellard
    "SUBB",
84 2c0262af bellard
    "SUBW",
85 2c0262af bellard
    "SUBL",
86 2c0262af bellard
    "SBBB",
87 2c0262af bellard
    "SBBW",
88 2c0262af bellard
    "SBBL",
89 2c0262af bellard
    "LOGICB",
90 2c0262af bellard
    "LOGICW",
91 2c0262af bellard
    "LOGICL",
92 2c0262af bellard
    "INCB",
93 2c0262af bellard
    "INCW",
94 2c0262af bellard
    "INCL",
95 2c0262af bellard
    "DECB",
96 2c0262af bellard
    "DECW",
97 2c0262af bellard
    "DECL",
98 2c0262af bellard
    "SHLB",
99 2c0262af bellard
    "SHLW",
100 2c0262af bellard
    "SHLL",
101 2c0262af bellard
    "SARB",
102 2c0262af bellard
    "SARW",
103 2c0262af bellard
    "SARL",
104 2c0262af bellard
};
105 2c0262af bellard
106 2c0262af bellard
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
107 2c0262af bellard
{
108 246d897f bellard
    int eflags, i;
109 2c0262af bellard
    char cc_op_name[32];
110 246d897f bellard
    static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
111 2c0262af bellard
112 2c0262af bellard
    eflags = env->eflags;
113 2c0262af bellard
    fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
114 2c0262af bellard
            "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
115 246d897f bellard
            "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]    CPL=%d\n",
116 2c0262af bellard
            env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
117 2c0262af bellard
            env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
118 2c0262af bellard
            env->eip, eflags,
119 2c0262af bellard
            eflags & DF_MASK ? 'D' : '-',
120 2c0262af bellard
            eflags & CC_O ? 'O' : '-',
121 2c0262af bellard
            eflags & CC_S ? 'S' : '-',
122 2c0262af bellard
            eflags & CC_Z ? 'Z' : '-',
123 2c0262af bellard
            eflags & CC_A ? 'A' : '-',
124 2c0262af bellard
            eflags & CC_P ? 'P' : '-',
125 246d897f bellard
            eflags & CC_C ? 'C' : '-',
126 246d897f bellard
            env->hflags & HF_CPL_MASK);
127 246d897f bellard
    for(i = 0; i < 6; i++) {
128 246d897f bellard
        SegmentCache *sc = &env->segs[i];
129 246d897f bellard
        fprintf(f, "%s =%04x %08x %08x %08x\n",
130 246d897f bellard
                seg_name[i],
131 246d897f bellard
                sc->selector,
132 246d897f bellard
                (int)sc->base,
133 246d897f bellard
                sc->limit,
134 246d897f bellard
                sc->flags);
135 246d897f bellard
    }
136 246d897f bellard
    fprintf(f, "LDT=%04x %08x %08x %08x\n",
137 246d897f bellard
            env->ldt.selector,
138 246d897f bellard
            (int)env->ldt.base,
139 246d897f bellard
            env->ldt.limit,
140 246d897f bellard
            env->ldt.flags);
141 246d897f bellard
    fprintf(f, "TR =%04x %08x %08x %08x\n",
142 246d897f bellard
            env->tr.selector,
143 246d897f bellard
            (int)env->tr.base,
144 246d897f bellard
            env->tr.limit,
145 246d897f bellard
            env->tr.flags);
146 246d897f bellard
    fprintf(f, "GDT=     %08x %08x\n",
147 246d897f bellard
            (int)env->gdt.base, env->gdt.limit);
148 246d897f bellard
    fprintf(f, "IDT=     %08x %08x\n",
149 246d897f bellard
            (int)env->idt.base, env->idt.limit);
150 246d897f bellard
    fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
151 246d897f bellard
            env->cr[0], env->cr[2], env->cr[3], env->cr[4]);
152 246d897f bellard
    
153 2c0262af bellard
    if (flags & X86_DUMP_CCOP) {
154 2c0262af bellard
        if ((unsigned)env->cc_op < CC_OP_NB)
155 2c0262af bellard
            strcpy(cc_op_name, cc_op_str[env->cc_op]);
156 2c0262af bellard
        else
157 2c0262af bellard
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
158 2c0262af bellard
        fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
159 2c0262af bellard
                env->cc_src, env->cc_dst, cc_op_name);
160 2c0262af bellard
    }
161 2c0262af bellard
    if (flags & X86_DUMP_FPU) {
162 2c0262af bellard
        fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
163 2c0262af bellard
                (double)env->fpregs[0], 
164 2c0262af bellard
                (double)env->fpregs[1], 
165 2c0262af bellard
                (double)env->fpregs[2], 
166 2c0262af bellard
                (double)env->fpregs[3]);
167 2c0262af bellard
        fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", 
168 2c0262af bellard
                (double)env->fpregs[4], 
169 2c0262af bellard
                (double)env->fpregs[5], 
170 2c0262af bellard
                (double)env->fpregs[7], 
171 2c0262af bellard
                (double)env->fpregs[8]);
172 2c0262af bellard
    }
173 2c0262af bellard
}
174 2c0262af bellard
175 2c0262af bellard
/***********************************************************/
176 2c0262af bellard
/* x86 mmu */
177 2c0262af bellard
/* XXX: add PGE support */
178 2c0262af bellard
179 2c0262af bellard
/* called when cr3 or PG bit are modified */
180 2c0262af bellard
static int last_pg_state = -1;
181 2c0262af bellard
static int last_pe_state = 0;
182 461c0471 bellard
static uint32_t a20_mask;
183 461c0471 bellard
int a20_enabled;
184 461c0471 bellard
185 2c0262af bellard
int phys_ram_size;
186 2c0262af bellard
int phys_ram_fd;
187 2c0262af bellard
uint8_t *phys_ram_base;
188 2c0262af bellard
189 461c0471 bellard
void cpu_x86_set_a20(CPUX86State *env, int a20_state)
190 461c0471 bellard
{
191 461c0471 bellard
    a20_state = (a20_state != 0);
192 461c0471 bellard
    if (a20_state != a20_enabled) {
193 461c0471 bellard
        /* when a20 is changed, all the MMU mappings are invalid, so
194 461c0471 bellard
           we must flush everything */
195 461c0471 bellard
        page_unmap();
196 461c0471 bellard
        tlb_flush(env);
197 461c0471 bellard
        a20_enabled = a20_state;
198 461c0471 bellard
        if (a20_enabled)
199 461c0471 bellard
            a20_mask = 0xffffffff;
200 461c0471 bellard
        else
201 461c0471 bellard
            a20_mask = 0xffefffff;
202 461c0471 bellard
    }
203 461c0471 bellard
}
204 461c0471 bellard
205 2c0262af bellard
void cpu_x86_update_cr0(CPUX86State *env)
206 2c0262af bellard
{
207 2c0262af bellard
    int pg_state, pe_state;
208 2c0262af bellard
209 2c0262af bellard
#ifdef DEBUG_MMU
210 2c0262af bellard
    printf("CR0 update: CR0=0x%08x\n", env->cr[0]);
211 2c0262af bellard
#endif
212 2c0262af bellard
    pg_state = env->cr[0] & CR0_PG_MASK;
213 2c0262af bellard
    if (pg_state != last_pg_state) {
214 2c0262af bellard
        page_unmap();
215 2c0262af bellard
        tlb_flush(env);
216 2c0262af bellard
        last_pg_state = pg_state;
217 2c0262af bellard
    }
218 2c0262af bellard
    pe_state = env->cr[0] & CR0_PE_MASK;
219 2c0262af bellard
    if (last_pe_state != pe_state) {
220 2c0262af bellard
        tb_flush();
221 2c0262af bellard
        last_pe_state = pe_state;
222 2c0262af bellard
    }
223 2c0262af bellard
}
224 2c0262af bellard
225 2c0262af bellard
void cpu_x86_update_cr3(CPUX86State *env)
226 2c0262af bellard
{
227 2c0262af bellard
    if (env->cr[0] & CR0_PG_MASK) {
228 2c0262af bellard
#if defined(DEBUG_MMU)
229 2c0262af bellard
        printf("CR3 update: CR3=%08x\n", env->cr[3]);
230 2c0262af bellard
#endif
231 2c0262af bellard
        page_unmap();
232 2c0262af bellard
        tlb_flush(env);
233 2c0262af bellard
    }
234 2c0262af bellard
}
235 2c0262af bellard
236 2c0262af bellard
void cpu_x86_init_mmu(CPUX86State *env)
237 2c0262af bellard
{
238 461c0471 bellard
    a20_enabled = 1;
239 461c0471 bellard
    a20_mask = 0xffffffff;
240 461c0471 bellard
241 2c0262af bellard
    last_pg_state = -1;
242 2c0262af bellard
    cpu_x86_update_cr0(env);
243 2c0262af bellard
}
244 2c0262af bellard
245 2c0262af bellard
/* XXX: also flush 4MB pages */
246 2c0262af bellard
void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
247 2c0262af bellard
{
248 2c0262af bellard
    int flags;
249 2c0262af bellard
    unsigned long virt_addr;
250 2c0262af bellard
251 2c0262af bellard
    tlb_flush_page(env, addr);
252 2c0262af bellard
253 2c0262af bellard
    flags = page_get_flags(addr);
254 2c0262af bellard
    if (flags & PAGE_VALID) {
255 2c0262af bellard
        virt_addr = addr & ~0xfff;
256 61382a50 bellard
#if !defined(CONFIG_SOFTMMU)
257 2c0262af bellard
        munmap((void *)virt_addr, 4096);
258 61382a50 bellard
#endif
259 2c0262af bellard
        page_set_flags(virt_addr, virt_addr + 4096, 0);
260 2c0262af bellard
    }
261 2c0262af bellard
}
262 2c0262af bellard
263 2c0262af bellard
/* return value:
264 2c0262af bellard
   -1 = cannot handle fault 
265 2c0262af bellard
   0  = nothing more to do 
266 2c0262af bellard
   1  = generate PF fault
267 2c0262af bellard
   2  = soft MMU activation required for this block
268 2c0262af bellard
*/
269 61382a50 bellard
int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, 
270 61382a50 bellard
                             int is_write, int is_user, int is_softmmu)
271 2c0262af bellard
{
272 2c0262af bellard
    uint8_t *pde_ptr, *pte_ptr;
273 2c0262af bellard
    uint32_t pde, pte, virt_addr;
274 61382a50 bellard
    int error_code, is_dirty, prot, page_size, ret;
275 2c0262af bellard
    unsigned long pd;
276 2c0262af bellard
    
277 2c0262af bellard
#ifdef DEBUG_MMU
278 2c0262af bellard
    printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", 
279 2c0262af bellard
           addr, is_write, is_user, env->eip);
280 2c0262af bellard
#endif
281 2c0262af bellard
282 2c0262af bellard
    if (env->user_mode_only) {
283 2c0262af bellard
        /* user mode only emulation */
284 2c0262af bellard
        error_code = 0;
285 2c0262af bellard
        goto do_fault;
286 2c0262af bellard
    }
287 2c0262af bellard
288 2c0262af bellard
    if (!(env->cr[0] & CR0_PG_MASK)) {
289 2c0262af bellard
        pte = addr;
290 461c0471 bellard
        virt_addr = addr & TARGET_PAGE_MASK;
291 2c0262af bellard
        prot = PROT_READ | PROT_WRITE;
292 2c0262af bellard
        page_size = 4096;
293 2c0262af bellard
        goto do_mapping;
294 2c0262af bellard
    }
295 2c0262af bellard
296 2c0262af bellard
    /* page directory entry */
297 461c0471 bellard
    pde_ptr = phys_ram_base + 
298 461c0471 bellard
        (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & a20_mask);
299 61382a50 bellard
    pde = ldl_raw(pde_ptr);
300 2c0262af bellard
    if (!(pde & PG_PRESENT_MASK)) {
301 2c0262af bellard
        error_code = 0;
302 2c0262af bellard
        goto do_fault;
303 2c0262af bellard
    }
304 2c0262af bellard
    if (is_user) {
305 2c0262af bellard
        if (!(pde & PG_USER_MASK))
306 2c0262af bellard
            goto do_fault_protect;
307 2c0262af bellard
        if (is_write && !(pde & PG_RW_MASK))
308 2c0262af bellard
            goto do_fault_protect;
309 2c0262af bellard
    } else {
310 2c0262af bellard
        if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) &&
311 2c0262af bellard
            is_write && !(pde & PG_RW_MASK)) 
312 2c0262af bellard
            goto do_fault_protect;
313 2c0262af bellard
    }
314 2c0262af bellard
    /* if PSE bit is set, then we use a 4MB page */
315 2c0262af bellard
    if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
316 2c0262af bellard
        is_dirty = is_write && !(pde & PG_DIRTY_MASK);
317 2c0262af bellard
        if (!(pde & PG_ACCESSED_MASK)) {
318 2c0262af bellard
            pde |= PG_ACCESSED_MASK;
319 2c0262af bellard
            if (is_dirty)
320 2c0262af bellard
                pde |= PG_DIRTY_MASK;
321 61382a50 bellard
            stl_raw(pde_ptr, pde);
322 2c0262af bellard
        }
323 2c0262af bellard
        
324 2c0262af bellard
        pte = pde & ~0x003ff000; /* align to 4MB */
325 2c0262af bellard
        page_size = 4096 * 1024;
326 2c0262af bellard
        virt_addr = addr & ~0x003fffff;
327 2c0262af bellard
    } else {
328 2c0262af bellard
        if (!(pde & PG_ACCESSED_MASK)) {
329 2c0262af bellard
            pde |= PG_ACCESSED_MASK;
330 61382a50 bellard
            stl_raw(pde_ptr, pde);
331 2c0262af bellard
        }
332 2c0262af bellard
333 2c0262af bellard
        /* page directory entry */
334 461c0471 bellard
        pte_ptr = phys_ram_base + 
335 461c0471 bellard
            (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask);
336 61382a50 bellard
        pte = ldl_raw(pte_ptr);
337 2c0262af bellard
        if (!(pte & PG_PRESENT_MASK)) {
338 2c0262af bellard
            error_code = 0;
339 2c0262af bellard
            goto do_fault;
340 2c0262af bellard
        }
341 2c0262af bellard
        if (is_user) {
342 2c0262af bellard
            if (!(pte & PG_USER_MASK))
343 2c0262af bellard
                goto do_fault_protect;
344 2c0262af bellard
            if (is_write && !(pte & PG_RW_MASK))
345 2c0262af bellard
                goto do_fault_protect;
346 2c0262af bellard
        } else {
347 2c0262af bellard
            if ((env->cr[0] & CR0_WP_MASK) && (pte & PG_USER_MASK) &&
348 2c0262af bellard
                is_write && !(pte & PG_RW_MASK)) 
349 2c0262af bellard
                goto do_fault_protect;
350 2c0262af bellard
        }
351 2c0262af bellard
        is_dirty = is_write && !(pte & PG_DIRTY_MASK);
352 2c0262af bellard
        if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
353 2c0262af bellard
            pte |= PG_ACCESSED_MASK;
354 2c0262af bellard
            if (is_dirty)
355 2c0262af bellard
                pte |= PG_DIRTY_MASK;
356 61382a50 bellard
            stl_raw(pte_ptr, pte);
357 2c0262af bellard
        }
358 2c0262af bellard
        page_size = 4096;
359 2c0262af bellard
        virt_addr = addr & ~0xfff;
360 2c0262af bellard
    }
361 2c0262af bellard
    /* the page can be put in the TLB */
362 2c0262af bellard
    prot = PROT_READ;
363 2c0262af bellard
    if (is_user) {
364 2c0262af bellard
        if (pte & PG_RW_MASK)
365 2c0262af bellard
            prot |= PROT_WRITE;
366 2c0262af bellard
    } else {
367 2c0262af bellard
        if (!(env->cr[0] & CR0_WP_MASK) || !(pte & PG_USER_MASK) ||
368 2c0262af bellard
            (pte & PG_RW_MASK))
369 2c0262af bellard
            prot |= PROT_WRITE;
370 2c0262af bellard
    }
371 2c0262af bellard
    
372 2c0262af bellard
 do_mapping:
373 461c0471 bellard
    pte = pte & a20_mask;
374 61382a50 bellard
#if !defined(CONFIG_SOFTMMU)
375 61382a50 bellard
    if (is_softmmu) 
376 61382a50 bellard
#endif
377 61382a50 bellard
    {
378 2c0262af bellard
        unsigned long paddr, vaddr, address, addend, page_offset;
379 2c0262af bellard
        int index;
380 2c0262af bellard
381 2c0262af bellard
        /* software MMU case. Even if 4MB pages, we map only one 4KB
382 2c0262af bellard
           page in the cache to avoid filling it too fast */
383 461c0471 bellard
        page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
384 461c0471 bellard
        paddr = (pte & TARGET_PAGE_MASK) + page_offset;
385 2c0262af bellard
        vaddr = virt_addr + page_offset;
386 2c0262af bellard
        index = (addr >> 12) & (CPU_TLB_SIZE - 1);
387 2c0262af bellard
        pd = physpage_find(paddr);
388 2c0262af bellard
        if (pd & 0xfff) {
389 2c0262af bellard
            /* IO memory case */
390 2c0262af bellard
            address = vaddr | pd;
391 2c0262af bellard
            addend = paddr;
392 2c0262af bellard
        } else {
393 2c0262af bellard
            /* standard memory */
394 2c0262af bellard
            address = vaddr;
395 2c0262af bellard
            addend = (unsigned long)phys_ram_base + pd;
396 2c0262af bellard
        }
397 2c0262af bellard
        addend -= vaddr;
398 2c0262af bellard
        env->tlb_read[is_user][index].address = address;
399 2c0262af bellard
        env->tlb_read[is_user][index].addend = addend;
400 2c0262af bellard
        if (prot & PROT_WRITE) {
401 2c0262af bellard
            env->tlb_write[is_user][index].address = address;
402 2c0262af bellard
            env->tlb_write[is_user][index].addend = addend;
403 2c0262af bellard
        }
404 61382a50 bellard
        page_set_flags(vaddr, vaddr + TARGET_PAGE_SIZE, 
405 61382a50 bellard
                       PAGE_VALID | PAGE_EXEC | prot);
406 61382a50 bellard
        ret = 0;
407 2c0262af bellard
    }
408 61382a50 bellard
#if !defined(CONFIG_SOFTMMU)
409 61382a50 bellard
    else {
410 61382a50 bellard
        ret = 0;
411 61382a50 bellard
        /* XXX: incorrect for 4MB pages */
412 61382a50 bellard
        pd = physpage_find(pte & ~0xfff);
413 61382a50 bellard
        if ((pd & 0xfff) != 0) {
414 61382a50 bellard
            /* IO access: no mapping is done as it will be handled by the
415 61382a50 bellard
               soft MMU */
416 61382a50 bellard
            if (!(env->hflags & HF_SOFTMMU_MASK))
417 61382a50 bellard
                ret = 2;
418 61382a50 bellard
        } else {
419 61382a50 bellard
            void *map_addr;
420 61382a50 bellard
            map_addr = mmap((void *)virt_addr, page_size, prot, 
421 61382a50 bellard
                            MAP_SHARED | MAP_FIXED, phys_ram_fd, pd);
422 61382a50 bellard
            if (map_addr == MAP_FAILED) {
423 61382a50 bellard
                fprintf(stderr, 
424 61382a50 bellard
                        "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n",
425 61382a50 bellard
                        pte & ~0xfff, virt_addr);
426 61382a50 bellard
                exit(1);
427 61382a50 bellard
            }
428 2c0262af bellard
#ifdef DEBUG_MMU
429 61382a50 bellard
            printf("mmaping 0x%08x to virt 0x%08x pse=%d\n", 
430 61382a50 bellard
                   pte & ~0xfff, virt_addr, (page_size != 4096));
431 2c0262af bellard
#endif
432 61382a50 bellard
            page_set_flags(virt_addr, virt_addr + page_size, 
433 61382a50 bellard
                           PAGE_VALID | PAGE_EXEC | prot);
434 61382a50 bellard
        }
435 2c0262af bellard
    }
436 61382a50 bellard
#endif
437 2c0262af bellard
    return ret;
438 2c0262af bellard
 do_fault_protect:
439 2c0262af bellard
    error_code = PG_ERROR_P_MASK;
440 2c0262af bellard
 do_fault:
441 2c0262af bellard
    env->cr[2] = addr;
442 2c0262af bellard
    env->error_code = (is_write << PG_ERROR_W_BIT) | error_code;
443 2c0262af bellard
    if (is_user)
444 2c0262af bellard
        env->error_code |= PG_ERROR_U_MASK;
445 2c0262af bellard
    return 1;
446 2c0262af bellard
}