Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ 07ce05ea

History | View | Annotate | Download (13 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
47 1ac157da bellard
    /* init to reset state */
48 1ac157da bellard
49 1ac157da bellard
    tlb_flush(env, 1);
50 2c0262af bellard
#ifdef CONFIG_SOFTMMU
51 2c0262af bellard
    env->hflags |= HF_SOFTMMU_MASK;
52 2c0262af bellard
#endif
53 1ac157da bellard
54 1ac157da bellard
    cpu_x86_update_cr0(env, 0x60000010);
55 1ac157da bellard
    env->a20_mask = 0xffffffff;
56 1ac157da bellard
    
57 1ac157da bellard
    env->idt.limit = 0xffff;
58 1ac157da bellard
    env->gdt.limit = 0xffff;
59 1ac157da bellard
    env->ldt.limit = 0xffff;
60 1ac157da bellard
    env->ldt.flags = DESC_P_MASK;
61 1ac157da bellard
    env->tr.limit = 0xffff;
62 1ac157da bellard
    env->tr.flags = DESC_P_MASK;
63 1ac157da bellard
    
64 1ac157da bellard
    /* not correct (CS base=0xffff0000) */
65 1ac157da bellard
    cpu_x86_load_seg_cache(env, R_CS, 0xf000, (uint8_t *)0x000f0000, 0xffff, 0); 
66 1ac157da bellard
    cpu_x86_load_seg_cache(env, R_DS, 0, NULL, 0xffff, 0);
67 1ac157da bellard
    cpu_x86_load_seg_cache(env, R_ES, 0, NULL, 0xffff, 0);
68 1ac157da bellard
    cpu_x86_load_seg_cache(env, R_SS, 0, NULL, 0xffff, 0);
69 1ac157da bellard
    cpu_x86_load_seg_cache(env, R_FS, 0, NULL, 0xffff, 0);
70 1ac157da bellard
    cpu_x86_load_seg_cache(env, R_GS, 0, NULL, 0xffff, 0);
71 1ac157da bellard
    
72 1ac157da bellard
    env->eip = 0xfff0;
73 1ac157da bellard
    env->regs[R_EDX] = 0x600; /* indicate P6 processor */
74 1ac157da bellard
    
75 1ac157da bellard
    env->eflags = 0x2;
76 1ac157da bellard
    
77 1ac157da bellard
    /* FPU init */
78 1ac157da bellard
    for(i = 0;i < 8; i++)
79 1ac157da bellard
        env->fptags[i] = 1;
80 1ac157da bellard
    env->fpuc = 0x37f;
81 1ac157da bellard
    
82 2c0262af bellard
    /* init various static tables */
83 2c0262af bellard
    if (!inited) {
84 2c0262af bellard
        inited = 1;
85 2c0262af bellard
        optimize_flags_init();
86 2c0262af bellard
    }
87 2c0262af bellard
    return env;
88 2c0262af bellard
}
89 2c0262af bellard
90 2c0262af bellard
void cpu_x86_close(CPUX86State *env)
91 2c0262af bellard
{
92 2c0262af bellard
    free(env);
93 2c0262af bellard
}
94 2c0262af bellard
95 2c0262af bellard
/***********************************************************/
96 2c0262af bellard
/* x86 debug */
97 2c0262af bellard
98 2c0262af bellard
static const char *cc_op_str[] = {
99 2c0262af bellard
    "DYNAMIC",
100 2c0262af bellard
    "EFLAGS",
101 b7f0f463 bellard
    "MULB",
102 b7f0f463 bellard
    "MULW",
103 b7f0f463 bellard
    "MULL",
104 2c0262af bellard
    "ADDB",
105 2c0262af bellard
    "ADDW",
106 2c0262af bellard
    "ADDL",
107 2c0262af bellard
    "ADCB",
108 2c0262af bellard
    "ADCW",
109 2c0262af bellard
    "ADCL",
110 2c0262af bellard
    "SUBB",
111 2c0262af bellard
    "SUBW",
112 2c0262af bellard
    "SUBL",
113 2c0262af bellard
    "SBBB",
114 2c0262af bellard
    "SBBW",
115 2c0262af bellard
    "SBBL",
116 2c0262af bellard
    "LOGICB",
117 2c0262af bellard
    "LOGICW",
118 2c0262af bellard
    "LOGICL",
119 2c0262af bellard
    "INCB",
120 2c0262af bellard
    "INCW",
121 2c0262af bellard
    "INCL",
122 2c0262af bellard
    "DECB",
123 2c0262af bellard
    "DECW",
124 2c0262af bellard
    "DECL",
125 2c0262af bellard
    "SHLB",
126 2c0262af bellard
    "SHLW",
127 2c0262af bellard
    "SHLL",
128 2c0262af bellard
    "SARB",
129 2c0262af bellard
    "SARW",
130 2c0262af bellard
    "SARL",
131 2c0262af bellard
};
132 2c0262af bellard
133 2c0262af bellard
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
134 2c0262af bellard
{
135 246d897f bellard
    int eflags, i;
136 2c0262af bellard
    char cc_op_name[32];
137 246d897f bellard
    static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
138 2c0262af bellard
139 2c0262af bellard
    eflags = env->eflags;
140 2c0262af bellard
    fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
141 2c0262af bellard
            "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
142 5e809a80 bellard
            "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]    CPL=%d II=%d\n",
143 2c0262af bellard
            env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
144 2c0262af bellard
            env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
145 2c0262af bellard
            env->eip, eflags,
146 2c0262af bellard
            eflags & DF_MASK ? 'D' : '-',
147 2c0262af bellard
            eflags & CC_O ? 'O' : '-',
148 2c0262af bellard
            eflags & CC_S ? 'S' : '-',
149 2c0262af bellard
            eflags & CC_Z ? 'Z' : '-',
150 2c0262af bellard
            eflags & CC_A ? 'A' : '-',
151 2c0262af bellard
            eflags & CC_P ? 'P' : '-',
152 246d897f bellard
            eflags & CC_C ? 'C' : '-',
153 5e809a80 bellard
            env->hflags & HF_CPL_MASK, 
154 5e809a80 bellard
            (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1);
155 246d897f bellard
    for(i = 0; i < 6; i++) {
156 246d897f bellard
        SegmentCache *sc = &env->segs[i];
157 246d897f bellard
        fprintf(f, "%s =%04x %08x %08x %08x\n",
158 246d897f bellard
                seg_name[i],
159 246d897f bellard
                sc->selector,
160 246d897f bellard
                (int)sc->base,
161 246d897f bellard
                sc->limit,
162 246d897f bellard
                sc->flags);
163 246d897f bellard
    }
164 246d897f bellard
    fprintf(f, "LDT=%04x %08x %08x %08x\n",
165 246d897f bellard
            env->ldt.selector,
166 246d897f bellard
            (int)env->ldt.base,
167 246d897f bellard
            env->ldt.limit,
168 246d897f bellard
            env->ldt.flags);
169 246d897f bellard
    fprintf(f, "TR =%04x %08x %08x %08x\n",
170 246d897f bellard
            env->tr.selector,
171 246d897f bellard
            (int)env->tr.base,
172 246d897f bellard
            env->tr.limit,
173 246d897f bellard
            env->tr.flags);
174 246d897f bellard
    fprintf(f, "GDT=     %08x %08x\n",
175 246d897f bellard
            (int)env->gdt.base, env->gdt.limit);
176 246d897f bellard
    fprintf(f, "IDT=     %08x %08x\n",
177 246d897f bellard
            (int)env->idt.base, env->idt.limit);
178 246d897f bellard
    fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
179 246d897f bellard
            env->cr[0], env->cr[2], env->cr[3], env->cr[4]);
180 246d897f bellard
    
181 2c0262af bellard
    if (flags & X86_DUMP_CCOP) {
182 2c0262af bellard
        if ((unsigned)env->cc_op < CC_OP_NB)
183 2c0262af bellard
            strcpy(cc_op_name, cc_op_str[env->cc_op]);
184 2c0262af bellard
        else
185 2c0262af bellard
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
186 2c0262af bellard
        fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
187 2c0262af bellard
                env->cc_src, env->cc_dst, cc_op_name);
188 2c0262af bellard
    }
189 2c0262af bellard
    if (flags & X86_DUMP_FPU) {
190 2c0262af bellard
        fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
191 2c0262af bellard
                (double)env->fpregs[0], 
192 2c0262af bellard
                (double)env->fpregs[1], 
193 2c0262af bellard
                (double)env->fpregs[2], 
194 2c0262af bellard
                (double)env->fpregs[3]);
195 2c0262af bellard
        fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", 
196 2c0262af bellard
                (double)env->fpregs[4], 
197 2c0262af bellard
                (double)env->fpregs[5], 
198 2c0262af bellard
                (double)env->fpregs[7], 
199 2c0262af bellard
                (double)env->fpregs[8]);
200 2c0262af bellard
    }
201 2c0262af bellard
}
202 2c0262af bellard
203 2c0262af bellard
/***********************************************************/
204 2c0262af bellard
/* x86 mmu */
205 2c0262af bellard
/* XXX: add PGE support */
206 2c0262af bellard
207 461c0471 bellard
void cpu_x86_set_a20(CPUX86State *env, int a20_state)
208 461c0471 bellard
{
209 461c0471 bellard
    a20_state = (a20_state != 0);
210 1ac157da bellard
    if (a20_state != ((env->a20_mask >> 20) & 1)) {
211 b7f0f463 bellard
#if defined(DEBUG_MMU)
212 b7f0f463 bellard
        printf("A20 update: a20=%d\n", a20_state);
213 b7f0f463 bellard
#endif
214 6bb70571 bellard
        /* if the cpu is currently executing code, we must unlink it and
215 6bb70571 bellard
           all the potentially executing TB */
216 6bb70571 bellard
        cpu_interrupt(env, 0);
217 6bb70571 bellard
218 461c0471 bellard
        /* when a20 is changed, all the MMU mappings are invalid, so
219 461c0471 bellard
           we must flush everything */
220 1ac157da bellard
        tlb_flush(env, 1);
221 1ac157da bellard
        env->a20_mask = 0xffefffff | (a20_state << 20);
222 461c0471 bellard
    }
223 461c0471 bellard
}
224 461c0471 bellard
225 1ac157da bellard
void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
226 2c0262af bellard
{
227 1ac157da bellard
    int pe_state;
228 2c0262af bellard
229 b7f0f463 bellard
#if defined(DEBUG_MMU)
230 1ac157da bellard
    printf("CR0 update: CR0=0x%08x\n", new_cr0);
231 2c0262af bellard
#endif
232 1ac157da bellard
    if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
233 1ac157da bellard
        (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
234 1ac157da bellard
        tlb_flush(env, 1);
235 2c0262af bellard
    }
236 1ac157da bellard
    env->cr[0] = new_cr0;
237 1ac157da bellard
    
238 436d8b89 bellard
    /* update PE flag in hidden flags */
239 436d8b89 bellard
    pe_state = (env->cr[0] & CR0_PE_MASK);
240 436d8b89 bellard
    env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
241 436d8b89 bellard
    /* ensure that ADDSEG is always set in real mode */
242 436d8b89 bellard
    env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
243 2c0262af bellard
}
244 2c0262af bellard
245 1ac157da bellard
void cpu_x86_update_cr3(CPUX86State *env, uint32_t new_cr3)
246 2c0262af bellard
{
247 1ac157da bellard
    env->cr[3] = new_cr3;
248 2c0262af bellard
    if (env->cr[0] & CR0_PG_MASK) {
249 2c0262af bellard
#if defined(DEBUG_MMU)
250 1ac157da bellard
        printf("CR3 update: CR3=%08x\n", new_cr3);
251 2c0262af bellard
#endif
252 1ac157da bellard
        tlb_flush(env, 0);
253 2c0262af bellard
    }
254 2c0262af bellard
}
255 2c0262af bellard
256 1ac157da bellard
void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
257 2c0262af bellard
{
258 1ac157da bellard
#if defined(DEBUG_MMU)
259 1ac157da bellard
    printf("CR4 update: CR4=%08x\n", env->cr[4]);
260 1ac157da bellard
#endif
261 1ac157da bellard
    if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
262 1ac157da bellard
        (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
263 1ac157da bellard
        tlb_flush(env, 1);
264 1ac157da bellard
    }
265 1ac157da bellard
    env->cr[4] = new_cr4;
266 2c0262af bellard
}
267 2c0262af bellard
268 2c0262af bellard
/* XXX: also flush 4MB pages */
269 2c0262af bellard
void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
270 2c0262af bellard
{
271 2c0262af bellard
    tlb_flush_page(env, addr);
272 2c0262af bellard
}
273 2c0262af bellard
274 2c0262af bellard
/* return value:
275 2c0262af bellard
   -1 = cannot handle fault 
276 2c0262af bellard
   0  = nothing more to do 
277 2c0262af bellard
   1  = generate PF fault
278 2c0262af bellard
   2  = soft MMU activation required for this block
279 2c0262af bellard
*/
280 61382a50 bellard
int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, 
281 61382a50 bellard
                             int is_write, int is_user, int is_softmmu)
282 2c0262af bellard
{
283 2c0262af bellard
    uint8_t *pde_ptr, *pte_ptr;
284 10f0e412 bellard
    uint32_t pde, pte, virt_addr, ptep;
285 61382a50 bellard
    int error_code, is_dirty, prot, page_size, ret;
286 436d8b89 bellard
    unsigned long paddr, vaddr, page_offset;
287 2c0262af bellard
    
288 436d8b89 bellard
#if defined(DEBUG_MMU)
289 2c0262af bellard
    printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", 
290 2c0262af bellard
           addr, is_write, is_user, env->eip);
291 2c0262af bellard
#endif
292 2c0262af bellard
293 2c0262af bellard
    if (env->user_mode_only) {
294 2c0262af bellard
        /* user mode only emulation */
295 2c0262af bellard
        error_code = 0;
296 2c0262af bellard
        goto do_fault;
297 2c0262af bellard
    }
298 2c0262af bellard
299 2c0262af bellard
    if (!(env->cr[0] & CR0_PG_MASK)) {
300 2c0262af bellard
        pte = addr;
301 461c0471 bellard
        virt_addr = addr & TARGET_PAGE_MASK;
302 2c0262af bellard
        prot = PROT_READ | PROT_WRITE;
303 2c0262af bellard
        page_size = 4096;
304 2c0262af bellard
        goto do_mapping;
305 2c0262af bellard
    }
306 2c0262af bellard
307 2c0262af bellard
    /* page directory entry */
308 461c0471 bellard
    pde_ptr = phys_ram_base + 
309 1ac157da bellard
        (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask);
310 61382a50 bellard
    pde = ldl_raw(pde_ptr);
311 2c0262af bellard
    if (!(pde & PG_PRESENT_MASK)) {
312 2c0262af bellard
        error_code = 0;
313 2c0262af bellard
        goto do_fault;
314 2c0262af bellard
    }
315 2c0262af bellard
    /* if PSE bit is set, then we use a 4MB page */
316 2c0262af bellard
    if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
317 10f0e412 bellard
        if (is_user) {
318 10f0e412 bellard
            if (!(pde & PG_USER_MASK))
319 10f0e412 bellard
                goto do_fault_protect;
320 10f0e412 bellard
            if (is_write && !(pde & PG_RW_MASK))
321 10f0e412 bellard
                goto do_fault_protect;
322 10f0e412 bellard
        } else {
323 34f715e7 bellard
            if ((env->cr[0] & CR0_WP_MASK) && 
324 10f0e412 bellard
                is_write && !(pde & PG_RW_MASK)) 
325 10f0e412 bellard
                goto do_fault_protect;
326 10f0e412 bellard
        }
327 2c0262af bellard
        is_dirty = is_write && !(pde & PG_DIRTY_MASK);
328 777aca2f bellard
        if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
329 2c0262af bellard
            pde |= PG_ACCESSED_MASK;
330 2c0262af bellard
            if (is_dirty)
331 2c0262af bellard
                pde |= PG_DIRTY_MASK;
332 61382a50 bellard
            stl_raw(pde_ptr, pde);
333 2c0262af bellard
        }
334 2c0262af bellard
        
335 2c0262af bellard
        pte = pde & ~0x003ff000; /* align to 4MB */
336 10f0e412 bellard
        ptep = pte;
337 2c0262af bellard
        page_size = 4096 * 1024;
338 2c0262af bellard
        virt_addr = addr & ~0x003fffff;
339 2c0262af bellard
    } else {
340 2c0262af bellard
        if (!(pde & PG_ACCESSED_MASK)) {
341 2c0262af bellard
            pde |= PG_ACCESSED_MASK;
342 61382a50 bellard
            stl_raw(pde_ptr, pde);
343 2c0262af bellard
        }
344 2c0262af bellard
345 2c0262af bellard
        /* page directory entry */
346 461c0471 bellard
        pte_ptr = phys_ram_base + 
347 1ac157da bellard
            (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask);
348 61382a50 bellard
        pte = ldl_raw(pte_ptr);
349 2c0262af bellard
        if (!(pte & PG_PRESENT_MASK)) {
350 2c0262af bellard
            error_code = 0;
351 2c0262af bellard
            goto do_fault;
352 2c0262af bellard
        }
353 10f0e412 bellard
        /* combine pde and pte user and rw protections */
354 10f0e412 bellard
        ptep = pte & pde;
355 2c0262af bellard
        if (is_user) {
356 10f0e412 bellard
            if (!(ptep & PG_USER_MASK))
357 2c0262af bellard
                goto do_fault_protect;
358 10f0e412 bellard
            if (is_write && !(ptep & PG_RW_MASK))
359 2c0262af bellard
                goto do_fault_protect;
360 2c0262af bellard
        } else {
361 34f715e7 bellard
            if ((env->cr[0] & CR0_WP_MASK) &&
362 10f0e412 bellard
                is_write && !(ptep & PG_RW_MASK)) 
363 2c0262af bellard
                goto do_fault_protect;
364 2c0262af bellard
        }
365 2c0262af bellard
        is_dirty = is_write && !(pte & PG_DIRTY_MASK);
366 2c0262af bellard
        if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
367 2c0262af bellard
            pte |= PG_ACCESSED_MASK;
368 2c0262af bellard
            if (is_dirty)
369 2c0262af bellard
                pte |= PG_DIRTY_MASK;
370 61382a50 bellard
            stl_raw(pte_ptr, pte);
371 2c0262af bellard
        }
372 2c0262af bellard
        page_size = 4096;
373 2c0262af bellard
        virt_addr = addr & ~0xfff;
374 2c0262af bellard
    }
375 c8135d9a bellard
376 2c0262af bellard
    /* the page can be put in the TLB */
377 2c0262af bellard
    prot = PROT_READ;
378 c8135d9a bellard
    if (pte & PG_DIRTY_MASK) {
379 c8135d9a bellard
        /* only set write access if already dirty... otherwise wait
380 c8135d9a bellard
           for dirty access */
381 c8135d9a bellard
        if (is_user) {
382 10f0e412 bellard
            if (ptep & PG_RW_MASK)
383 c8135d9a bellard
                prot |= PROT_WRITE;
384 c8135d9a bellard
        } else {
385 34f715e7 bellard
            if (!(env->cr[0] & CR0_WP_MASK) ||
386 10f0e412 bellard
                (ptep & PG_RW_MASK))
387 c8135d9a bellard
                prot |= PROT_WRITE;
388 c8135d9a bellard
        }
389 2c0262af bellard
    }
390 777aca2f bellard
391 2c0262af bellard
 do_mapping:
392 1ac157da bellard
    pte = pte & env->a20_mask;
393 2c0262af bellard
394 436d8b89 bellard
    /* Even if 4MB pages, we map only one 4KB page in the cache to
395 436d8b89 bellard
       avoid filling it too fast */
396 436d8b89 bellard
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
397 436d8b89 bellard
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
398 436d8b89 bellard
    vaddr = virt_addr + page_offset;
399 436d8b89 bellard
    
400 436d8b89 bellard
    ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
401 2c0262af bellard
    return ret;
402 2c0262af bellard
 do_fault_protect:
403 2c0262af bellard
    error_code = PG_ERROR_P_MASK;
404 2c0262af bellard
 do_fault:
405 2c0262af bellard
    env->cr[2] = addr;
406 2c0262af bellard
    env->error_code = (is_write << PG_ERROR_W_BIT) | error_code;
407 2c0262af bellard
    if (is_user)
408 2c0262af bellard
        env->error_code |= PG_ERROR_U_MASK;
409 2c0262af bellard
    return 1;
410 2c0262af bellard
}
411 10f0e412 bellard
412 10f0e412 bellard
#if defined(CONFIG_USER_ONLY) 
413 10f0e412 bellard
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
414 10f0e412 bellard
{
415 10f0e412 bellard
    return addr;
416 10f0e412 bellard
}
417 10f0e412 bellard
#else
418 10f0e412 bellard
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
419 10f0e412 bellard
{
420 10f0e412 bellard
    uint8_t *pde_ptr, *pte_ptr;
421 10f0e412 bellard
    uint32_t pde, pte, paddr, page_offset, page_size;
422 10f0e412 bellard
423 10f0e412 bellard
    if (!(env->cr[0] & CR0_PG_MASK)) {
424 10f0e412 bellard
        pte = addr;
425 10f0e412 bellard
        page_size = 4096;
426 10f0e412 bellard
    } else {
427 10f0e412 bellard
        /* page directory entry */
428 10f0e412 bellard
        pde_ptr = phys_ram_base + 
429 1ac157da bellard
            (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask);
430 10f0e412 bellard
        pde = ldl_raw(pde_ptr);
431 10f0e412 bellard
        if (!(pde & PG_PRESENT_MASK)) 
432 10f0e412 bellard
            return -1;
433 10f0e412 bellard
        if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
434 10f0e412 bellard
            pte = pde & ~0x003ff000; /* align to 4MB */
435 10f0e412 bellard
            page_size = 4096 * 1024;
436 10f0e412 bellard
        } else {
437 10f0e412 bellard
            /* page directory entry */
438 10f0e412 bellard
            pte_ptr = phys_ram_base + 
439 1ac157da bellard
                (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask);
440 10f0e412 bellard
            pte = ldl_raw(pte_ptr);
441 10f0e412 bellard
            if (!(pte & PG_PRESENT_MASK))
442 10f0e412 bellard
                return -1;
443 10f0e412 bellard
            page_size = 4096;
444 10f0e412 bellard
        }
445 10f0e412 bellard
    }
446 1ac157da bellard
    pte = pte & env->a20_mask;
447 10f0e412 bellard
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
448 10f0e412 bellard
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
449 10f0e412 bellard
    return paddr;
450 10f0e412 bellard
}
451 10f0e412 bellard
#endif