Statistics
| Branch: | Revision:

root / helper2-i386.c @ b67d5959

History | View | Annotate | Download (10.9 kB)

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