Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ 5fafdf24

History | View | Annotate | Download (32.6 kB)

1 2c0262af bellard
/*
2 2c0262af bellard
 *  i386 helpers (without register variable usage)
3 5fafdf24 ths
 *
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
28 2c0262af bellard
#include "cpu.h"
29 2c0262af bellard
#include "exec-all.h"
30 2c0262af bellard
31 2c0262af bellard
//#define DEBUG_MMU
32 2c0262af bellard
33 0e4b179d bellard
#ifdef USE_CODE_COPY
34 0e4b179d bellard
#include <asm/ldt.h>
35 0e4b179d bellard
#include <linux/unistd.h>
36 73bdea19 bellard
#include <linux/version.h>
37 0e4b179d bellard
38 83fcb515 bellard
int modify_ldt(int func, void *ptr, unsigned long bytecount)
39 83fcb515 bellard
{
40 83fcb515 bellard
        return syscall(__NR_modify_ldt, func, ptr, bytecount);
41 83fcb515 bellard
}
42 73bdea19 bellard
43 73bdea19 bellard
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
44 73bdea19 bellard
#define modify_ldt_ldt_s user_desc
45 0e4b179d bellard
#endif
46 73bdea19 bellard
#endif /* USE_CODE_COPY */
47 0e4b179d bellard
48 2c0262af bellard
CPUX86State *cpu_x86_init(void)
49 2c0262af bellard
{
50 2c0262af bellard
    CPUX86State *env;
51 2c0262af bellard
    static int inited;
52 2c0262af bellard
53 173d6cfe bellard
    env = qemu_mallocz(sizeof(CPUX86State));
54 2c0262af bellard
    if (!env)
55 2c0262af bellard
        return NULL;
56 173d6cfe bellard
    cpu_exec_init(env);
57 173d6cfe bellard
58 ffddfee3 bellard
    /* init various static tables */
59 ffddfee3 bellard
    if (!inited) {
60 ffddfee3 bellard
        inited = 1;
61 ffddfee3 bellard
        optimize_flags_init();
62 ffddfee3 bellard
    }
63 ffddfee3 bellard
#ifdef USE_CODE_COPY
64 ffddfee3 bellard
    /* testing code for code copy case */
65 ffddfee3 bellard
    {
66 ffddfee3 bellard
        struct modify_ldt_ldt_s ldt;
67 2c0262af bellard
68 ffddfee3 bellard
        ldt.entry_number = 1;
69 ffddfee3 bellard
        ldt.base_addr = (unsigned long)env;
70 ffddfee3 bellard
        ldt.limit = (sizeof(CPUState) + 0xfff) >> 12;
71 ffddfee3 bellard
        ldt.seg_32bit = 1;
72 ffddfee3 bellard
        ldt.contents = MODIFY_LDT_CONTENTS_DATA;
73 ffddfee3 bellard
        ldt.read_exec_only = 0;
74 ffddfee3 bellard
        ldt.limit_in_pages = 1;
75 ffddfee3 bellard
        ldt.seg_not_present = 0;
76 ffddfee3 bellard
        ldt.useable = 1;
77 ffddfee3 bellard
        modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
78 5fafdf24 ths
       
79 ffddfee3 bellard
        asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7));
80 ffddfee3 bellard
    }
81 ffddfee3 bellard
#endif
82 14ce26e7 bellard
    {
83 14ce26e7 bellard
        int family, model, stepping;
84 14ce26e7 bellard
#ifdef TARGET_X86_64
85 14ce26e7 bellard
        env->cpuid_vendor1 = 0x68747541; /* "Auth" */
86 14ce26e7 bellard
        env->cpuid_vendor2 = 0x69746e65; /* "enti" */
87 14ce26e7 bellard
        env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */
88 14ce26e7 bellard
        family = 6;
89 14ce26e7 bellard
        model = 2;
90 14ce26e7 bellard
        stepping = 3;
91 14ce26e7 bellard
#else
92 14ce26e7 bellard
        env->cpuid_vendor1 = 0x756e6547; /* "Genu" */
93 14ce26e7 bellard
        env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
94 14ce26e7 bellard
        env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
95 14ce26e7 bellard
#if 0
96 14ce26e7 bellard
        /* pentium 75-200 */
97 14ce26e7 bellard
        family = 5;
98 14ce26e7 bellard
        model = 2;
99 14ce26e7 bellard
        stepping = 11;
100 14ce26e7 bellard
#else
101 14ce26e7 bellard
        /* pentium pro */
102 14ce26e7 bellard
        family = 6;
103 bf079a1e bellard
        model = 3;
104 14ce26e7 bellard
        stepping = 3;
105 14ce26e7 bellard
#endif
106 14ce26e7 bellard
#endif
107 a6f37988 bellard
        env->cpuid_level = 2;
108 14ce26e7 bellard
        env->cpuid_version = (family << 8) | (model << 4) | stepping;
109 14ce26e7 bellard
        env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE |
110 14ce26e7 bellard
                               CPUID_TSC | CPUID_MSR | CPUID_MCE |
111 8f091a59 bellard
                               CPUID_CX8 | CPUID_PGE | CPUID_CMOV |
112 8f091a59 bellard
                               CPUID_PAT);
113 8f091a59 bellard
        env->pat = 0x0007040600070406ULL;
114 465e9838 bellard
        env->cpuid_ext_features = CPUID_EXT_SSE3;
115 bf079a1e bellard
        env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | CPUID_PAE | CPUID_SEP;
116 96b74a02 bellard
        env->cpuid_features |= CPUID_APIC;
117 408e7837 ths
        env->cpuid_xlevel = 0x80000006;
118 a6f37988 bellard
        {
119 a6f37988 bellard
            const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
120 a6f37988 bellard
            int c, len, i;
121 a6f37988 bellard
            len = strlen(model_id);
122 a6f37988 bellard
            for(i = 0; i < 48; i++) {
123 a6f37988 bellard
                if (i >= len)
124 a6f37988 bellard
                    c = '\0';
125 a6f37988 bellard
                else
126 a6f37988 bellard
                    c = model_id[i];
127 a6f37988 bellard
                env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
128 a6f37988 bellard
            }
129 a6f37988 bellard
        }
130 14ce26e7 bellard
#ifdef TARGET_X86_64
131 14ce26e7 bellard
        /* currently not enabled for std i386 because not fully tested */
132 a6f37988 bellard
        env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF);
133 4b4f782c bellard
        env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX;
134 a6f37988 bellard
        env->cpuid_xlevel = 0x80000008;
135 8f091a59 bellard
136 8f091a59 bellard
        /* these features are needed for Win64 and aren't fully implemented */
137 8f091a59 bellard
        env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA;
138 69c3bcb4 bellard
        /* this feature is needed for Solaris and isn't fully implemented */
139 69c3bcb4 bellard
        env->cpuid_features |= CPUID_PSE36;
140 14ce26e7 bellard
#endif
141 14ce26e7 bellard
    }
142 ffddfee3 bellard
    cpu_reset(env);
143 bf079a1e bellard
#ifdef USE_KQEMU
144 bf079a1e bellard
    kqemu_init(env);
145 bf079a1e bellard
#endif
146 ffddfee3 bellard
    return env;
147 ffddfee3 bellard
}
148 ffddfee3 bellard
149 ffddfee3 bellard
/* NOTE: must be called outside the CPU execute loop */
150 ffddfee3 bellard
void cpu_reset(CPUX86State *env)
151 ffddfee3 bellard
{
152 ffddfee3 bellard
    int i;
153 ffddfee3 bellard
154 ffddfee3 bellard
    memset(env, 0, offsetof(CPUX86State, breakpoints));
155 1ac157da bellard
156 1ac157da bellard
    tlb_flush(env, 1);
157 ffddfee3 bellard
158 a2cce02c ths
    env->old_exception = -1;
159 a2cce02c ths
160 ffddfee3 bellard
    /* init to reset state */
161 ffddfee3 bellard
162 2c0262af bellard
#ifdef CONFIG_SOFTMMU
163 2c0262af bellard
    env->hflags |= HF_SOFTMMU_MASK;
164 2c0262af bellard
#endif
165 1ac157da bellard
166 1ac157da bellard
    cpu_x86_update_cr0(env, 0x60000010);
167 1ac157da bellard
    env->a20_mask = 0xffffffff;
168 3b21e03e bellard
    env->smbase = 0x30000;
169 3b21e03e bellard
170 1ac157da bellard
    env->idt.limit = 0xffff;
171 1ac157da bellard
    env->gdt.limit = 0xffff;
172 1ac157da bellard
    env->ldt.limit = 0xffff;
173 1ac157da bellard
    env->ldt.flags = DESC_P_MASK;
174 1ac157da bellard
    env->tr.limit = 0xffff;
175 1ac157da bellard
    env->tr.flags = DESC_P_MASK;
176 5fafdf24 ths
   
177 5fafdf24 ths
    cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, 0);
178 14ce26e7 bellard
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, 0);
179 14ce26e7 bellard
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, 0);
180 14ce26e7 bellard
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, 0);
181 14ce26e7 bellard
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, 0);
182 14ce26e7 bellard
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0);
183 5fafdf24 ths
   
184 1ac157da bellard
    env->eip = 0xfff0;
185 1ac157da bellard
    env->regs[R_EDX] = 0x600; /* indicate P6 processor */
186 5fafdf24 ths
   
187 1ac157da bellard
    env->eflags = 0x2;
188 5fafdf24 ths
   
189 1ac157da bellard
    /* FPU init */
190 1ac157da bellard
    for(i = 0;i < 8; i++)
191 1ac157da bellard
        env->fptags[i] = 1;
192 1ac157da bellard
    env->fpuc = 0x37f;
193 664e0f19 bellard
194 664e0f19 bellard
    env->mxcsr = 0x1f80;
195 2c0262af bellard
}
196 2c0262af bellard
197 2c0262af bellard
void cpu_x86_close(CPUX86State *env)
198 2c0262af bellard
{
199 2c0262af bellard
    free(env);
200 2c0262af bellard
}
201 2c0262af bellard
202 2c0262af bellard
/***********************************************************/
203 2c0262af bellard
/* x86 debug */
204 2c0262af bellard
205 2c0262af bellard
static const char *cc_op_str[] = {
206 2c0262af bellard
    "DYNAMIC",
207 2c0262af bellard
    "EFLAGS",
208 14ce26e7 bellard
209 b7f0f463 bellard
    "MULB",
210 b7f0f463 bellard
    "MULW",
211 b7f0f463 bellard
    "MULL",
212 14ce26e7 bellard
    "MULQ",
213 14ce26e7 bellard
214 2c0262af bellard
    "ADDB",
215 2c0262af bellard
    "ADDW",
216 2c0262af bellard
    "ADDL",
217 14ce26e7 bellard
    "ADDQ",
218 14ce26e7 bellard
219 2c0262af bellard
    "ADCB",
220 2c0262af bellard
    "ADCW",
221 2c0262af bellard
    "ADCL",
222 14ce26e7 bellard
    "ADCQ",
223 14ce26e7 bellard
224 2c0262af bellard
    "SUBB",
225 2c0262af bellard
    "SUBW",
226 2c0262af bellard
    "SUBL",
227 14ce26e7 bellard
    "SUBQ",
228 14ce26e7 bellard
229 2c0262af bellard
    "SBBB",
230 2c0262af bellard
    "SBBW",
231 2c0262af bellard
    "SBBL",
232 14ce26e7 bellard
    "SBBQ",
233 14ce26e7 bellard
234 2c0262af bellard
    "LOGICB",
235 2c0262af bellard
    "LOGICW",
236 2c0262af bellard
    "LOGICL",
237 14ce26e7 bellard
    "LOGICQ",
238 14ce26e7 bellard
239 2c0262af bellard
    "INCB",
240 2c0262af bellard
    "INCW",
241 2c0262af bellard
    "INCL",
242 14ce26e7 bellard
    "INCQ",
243 14ce26e7 bellard
244 2c0262af bellard
    "DECB",
245 2c0262af bellard
    "DECW",
246 2c0262af bellard
    "DECL",
247 14ce26e7 bellard
    "DECQ",
248 14ce26e7 bellard
249 2c0262af bellard
    "SHLB",
250 2c0262af bellard
    "SHLW",
251 2c0262af bellard
    "SHLL",
252 14ce26e7 bellard
    "SHLQ",
253 14ce26e7 bellard
254 2c0262af bellard
    "SARB",
255 2c0262af bellard
    "SARW",
256 2c0262af bellard
    "SARL",
257 14ce26e7 bellard
    "SARQ",
258 2c0262af bellard
};
259 2c0262af bellard
260 5fafdf24 ths
void cpu_dump_state(CPUState *env, FILE *f,
261 7fe48483 bellard
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
262 7fe48483 bellard
                    int flags)
263 2c0262af bellard
{
264 2157fa06 bellard
    int eflags, i, nb;
265 2c0262af bellard
    char cc_op_name[32];
266 246d897f bellard
    static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
267 2c0262af bellard
268 2c0262af bellard
    eflags = env->eflags;
269 14ce26e7 bellard
#ifdef TARGET_X86_64
270 14ce26e7 bellard
    if (env->hflags & HF_CS64_MASK) {
271 5fafdf24 ths
        cpu_fprintf(f,
272 26a76461 bellard
                    "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
273 26a76461 bellard
                    "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
274 26a76461 bellard
                    "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
275 26a76461 bellard
                    "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
276 3b21e03e bellard
                    "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
277 5fafdf24 ths
                    env->regs[R_EAX],
278 5fafdf24 ths
                    env->regs[R_EBX],
279 5fafdf24 ths
                    env->regs[R_ECX],
280 5fafdf24 ths
                    env->regs[R_EDX],
281 5fafdf24 ths
                    env->regs[R_ESI],
282 5fafdf24 ths
                    env->regs[R_EDI],
283 5fafdf24 ths
                    env->regs[R_EBP],
284 5fafdf24 ths
                    env->regs[R_ESP],
285 5fafdf24 ths
                    env->regs[8],
286 5fafdf24 ths
                    env->regs[9],
287 5fafdf24 ths
                    env->regs[10],
288 5fafdf24 ths
                    env->regs[11],
289 5fafdf24 ths
                    env->regs[12],
290 5fafdf24 ths
                    env->regs[13],
291 5fafdf24 ths
                    env->regs[14],
292 5fafdf24 ths
                    env->regs[15],
293 14ce26e7 bellard
                    env->eip, eflags,
294 14ce26e7 bellard
                    eflags & DF_MASK ? 'D' : '-',
295 14ce26e7 bellard
                    eflags & CC_O ? 'O' : '-',
296 14ce26e7 bellard
                    eflags & CC_S ? 'S' : '-',
297 14ce26e7 bellard
                    eflags & CC_Z ? 'Z' : '-',
298 14ce26e7 bellard
                    eflags & CC_A ? 'A' : '-',
299 14ce26e7 bellard
                    eflags & CC_P ? 'P' : '-',
300 14ce26e7 bellard
                    eflags & CC_C ? 'C' : '-',
301 5fafdf24 ths
                    env->hflags & HF_CPL_MASK,
302 14ce26e7 bellard
                    (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
303 d2ac63e0 bellard
                    (env->a20_mask >> 20) & 1,
304 3b21e03e bellard
                    (env->hflags >> HF_SMM_SHIFT) & 1,
305 d2ac63e0 bellard
                    (env->hflags >> HF_HALTED_SHIFT) & 1);
306 5fafdf24 ths
    } else
307 14ce26e7 bellard
#endif
308 14ce26e7 bellard
    {
309 14ce26e7 bellard
        cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
310 14ce26e7 bellard
                    "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
311 3b21e03e bellard
                    "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
312 5fafdf24 ths
                    (uint32_t)env->regs[R_EAX],
313 5fafdf24 ths
                    (uint32_t)env->regs[R_EBX],
314 5fafdf24 ths
                    (uint32_t)env->regs[R_ECX],
315 5fafdf24 ths
                    (uint32_t)env->regs[R_EDX],
316 5fafdf24 ths
                    (uint32_t)env->regs[R_ESI],
317 5fafdf24 ths
                    (uint32_t)env->regs[R_EDI],
318 5fafdf24 ths
                    (uint32_t)env->regs[R_EBP],
319 5fafdf24 ths
                    (uint32_t)env->regs[R_ESP],
320 14ce26e7 bellard
                    (uint32_t)env->eip, eflags,
321 14ce26e7 bellard
                    eflags & DF_MASK ? 'D' : '-',
322 14ce26e7 bellard
                    eflags & CC_O ? 'O' : '-',
323 14ce26e7 bellard
                    eflags & CC_S ? 'S' : '-',
324 14ce26e7 bellard
                    eflags & CC_Z ? 'Z' : '-',
325 14ce26e7 bellard
                    eflags & CC_A ? 'A' : '-',
326 14ce26e7 bellard
                    eflags & CC_P ? 'P' : '-',
327 14ce26e7 bellard
                    eflags & CC_C ? 'C' : '-',
328 5fafdf24 ths
                    env->hflags & HF_CPL_MASK,
329 14ce26e7 bellard
                    (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
330 d2ac63e0 bellard
                    (env->a20_mask >> 20) & 1,
331 3b21e03e bellard
                    (env->hflags >> HF_SMM_SHIFT) & 1,
332 d2ac63e0 bellard
                    (env->hflags >> HF_HALTED_SHIFT) & 1);
333 14ce26e7 bellard
    }
334 14ce26e7 bellard
335 14ce26e7 bellard
#ifdef TARGET_X86_64
336 14ce26e7 bellard
    if (env->hflags & HF_LMA_MASK) {
337 14ce26e7 bellard
        for(i = 0; i < 6; i++) {
338 14ce26e7 bellard
            SegmentCache *sc = &env->segs[i];
339 26a76461 bellard
            cpu_fprintf(f, "%s =%04x %016" PRIx64 " %08x %08x\n",
340 14ce26e7 bellard
                        seg_name[i],
341 14ce26e7 bellard
                        sc->selector,
342 14ce26e7 bellard
                        sc->base,
343 14ce26e7 bellard
                        sc->limit,
344 14ce26e7 bellard
                        sc->flags);
345 14ce26e7 bellard
        }
346 26a76461 bellard
        cpu_fprintf(f, "LDT=%04x %016" PRIx64 " %08x %08x\n",
347 14ce26e7 bellard
                    env->ldt.selector,
348 14ce26e7 bellard
                    env->ldt.base,
349 14ce26e7 bellard
                    env->ldt.limit,
350 14ce26e7 bellard
                    env->ldt.flags);
351 26a76461 bellard
        cpu_fprintf(f, "TR =%04x %016" PRIx64 " %08x %08x\n",
352 14ce26e7 bellard
                    env->tr.selector,
353 14ce26e7 bellard
                    env->tr.base,
354 14ce26e7 bellard
                    env->tr.limit,
355 14ce26e7 bellard
                    env->tr.flags);
356 26a76461 bellard
        cpu_fprintf(f, "GDT=     %016" PRIx64 " %08x\n",
357 14ce26e7 bellard
                    env->gdt.base, env->gdt.limit);
358 26a76461 bellard
        cpu_fprintf(f, "IDT=     %016" PRIx64 " %08x\n",
359 14ce26e7 bellard
                    env->idt.base, env->idt.limit);
360 26a76461 bellard
        cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
361 5fafdf24 ths
                    (uint32_t)env->cr[0],
362 5fafdf24 ths
                    env->cr[2],
363 5fafdf24 ths
                    env->cr[3],
364 14ce26e7 bellard
                    (uint32_t)env->cr[4]);
365 14ce26e7 bellard
    } else
366 14ce26e7 bellard
#endif
367 14ce26e7 bellard
    {
368 14ce26e7 bellard
        for(i = 0; i < 6; i++) {
369 14ce26e7 bellard
            SegmentCache *sc = &env->segs[i];
370 14ce26e7 bellard
            cpu_fprintf(f, "%s =%04x %08x %08x %08x\n",
371 14ce26e7 bellard
                        seg_name[i],
372 14ce26e7 bellard
                        sc->selector,
373 14ce26e7 bellard
                        (uint32_t)sc->base,
374 14ce26e7 bellard
                        sc->limit,
375 14ce26e7 bellard
                        sc->flags);
376 14ce26e7 bellard
        }
377 14ce26e7 bellard
        cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n",
378 14ce26e7 bellard
                    env->ldt.selector,
379 14ce26e7 bellard
                    (uint32_t)env->ldt.base,
380 14ce26e7 bellard
                    env->ldt.limit,
381 14ce26e7 bellard
                    env->ldt.flags);
382 14ce26e7 bellard
        cpu_fprintf(f, "TR =%04x %08x %08x %08x\n",
383 14ce26e7 bellard
                    env->tr.selector,
384 14ce26e7 bellard
                    (uint32_t)env->tr.base,
385 14ce26e7 bellard
                    env->tr.limit,
386 14ce26e7 bellard
                    env->tr.flags);
387 14ce26e7 bellard
        cpu_fprintf(f, "GDT=     %08x %08x\n",
388 14ce26e7 bellard
                    (uint32_t)env->gdt.base, env->gdt.limit);
389 14ce26e7 bellard
        cpu_fprintf(f, "IDT=     %08x %08x\n",
390 14ce26e7 bellard
                    (uint32_t)env->idt.base, env->idt.limit);
391 14ce26e7 bellard
        cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
392 5fafdf24 ths
                    (uint32_t)env->cr[0],
393 5fafdf24 ths
                    (uint32_t)env->cr[2],
394 5fafdf24 ths
                    (uint32_t)env->cr[3],
395 14ce26e7 bellard
                    (uint32_t)env->cr[4]);
396 246d897f bellard
    }
397 2c0262af bellard
    if (flags & X86_DUMP_CCOP) {
398 2c0262af bellard
        if ((unsigned)env->cc_op < CC_OP_NB)
399 eba2af63 bellard
            snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
400 2c0262af bellard
        else
401 2c0262af bellard
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
402 14ce26e7 bellard
#ifdef TARGET_X86_64
403 14ce26e7 bellard
        if (env->hflags & HF_CS64_MASK) {
404 26a76461 bellard
            cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
405 5fafdf24 ths
                        env->cc_src, env->cc_dst,
406 14ce26e7 bellard
                        cc_op_name);
407 5fafdf24 ths
        } else
408 14ce26e7 bellard
#endif
409 14ce26e7 bellard
        {
410 14ce26e7 bellard
            cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
411 5fafdf24 ths
                        (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
412 14ce26e7 bellard
                        cc_op_name);
413 14ce26e7 bellard
        }
414 2c0262af bellard
    }
415 2c0262af bellard
    if (flags & X86_DUMP_FPU) {
416 2157fa06 bellard
        int fptag;
417 2157fa06 bellard
        fptag = 0;
418 2157fa06 bellard
        for(i = 0; i < 8; i++) {
419 2157fa06 bellard
            fptag |= ((!env->fptags[i]) << i);
420 2157fa06 bellard
        }
421 2157fa06 bellard
        cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
422 2157fa06 bellard
                    env->fpuc,
423 2157fa06 bellard
                    (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
424 2157fa06 bellard
                    env->fpstt,
425 2157fa06 bellard
                    fptag,
426 2157fa06 bellard
                    env->mxcsr);
427 2157fa06 bellard
        for(i=0;i<8;i++) {
428 2157fa06 bellard
#if defined(USE_X86LDOUBLE)
429 2157fa06 bellard
            union {
430 2157fa06 bellard
                long double d;
431 2157fa06 bellard
                struct {
432 2157fa06 bellard
                    uint64_t lower;
433 2157fa06 bellard
                    uint16_t upper;
434 2157fa06 bellard
                } l;
435 2157fa06 bellard
            } tmp;
436 2157fa06 bellard
            tmp.d = env->fpregs[i].d;
437 26a76461 bellard
            cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
438 2157fa06 bellard
                        i, tmp.l.lower, tmp.l.upper);
439 2157fa06 bellard
#else
440 26a76461 bellard
            cpu_fprintf(f, "FPR%d=%016" PRIx64,
441 2157fa06 bellard
                        i, env->fpregs[i].mmx.q);
442 2157fa06 bellard
#endif
443 2157fa06 bellard
            if ((i & 1) == 1)
444 2157fa06 bellard
                cpu_fprintf(f, "\n");
445 2157fa06 bellard
            else
446 2157fa06 bellard
                cpu_fprintf(f, " ");
447 2157fa06 bellard
        }
448 5fafdf24 ths
        if (env->hflags & HF_CS64_MASK)
449 2157fa06 bellard
            nb = 16;
450 2157fa06 bellard
        else
451 2157fa06 bellard
            nb = 8;
452 2157fa06 bellard
        for(i=0;i<nb;i++) {
453 2157fa06 bellard
            cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
454 5fafdf24 ths
                        i,
455 2157fa06 bellard
                        env->xmm_regs[i].XMM_L(3),
456 2157fa06 bellard
                        env->xmm_regs[i].XMM_L(2),
457 2157fa06 bellard
                        env->xmm_regs[i].XMM_L(1),
458 2157fa06 bellard
                        env->xmm_regs[i].XMM_L(0));
459 2157fa06 bellard
            if ((i & 1) == 1)
460 2157fa06 bellard
                cpu_fprintf(f, "\n");
461 2157fa06 bellard
            else
462 2157fa06 bellard
                cpu_fprintf(f, " ");
463 2157fa06 bellard
        }
464 2c0262af bellard
    }
465 2c0262af bellard
}
466 2c0262af bellard
467 2c0262af bellard
/***********************************************************/
468 2c0262af bellard
/* x86 mmu */
469 2c0262af bellard
/* XXX: add PGE support */
470 2c0262af bellard
471 461c0471 bellard
void cpu_x86_set_a20(CPUX86State *env, int a20_state)
472 461c0471 bellard
{
473 461c0471 bellard
    a20_state = (a20_state != 0);
474 1ac157da bellard
    if (a20_state != ((env->a20_mask >> 20) & 1)) {
475 b7f0f463 bellard
#if defined(DEBUG_MMU)
476 b7f0f463 bellard
        printf("A20 update: a20=%d\n", a20_state);
477 b7f0f463 bellard
#endif
478 6bb70571 bellard
        /* if the cpu is currently executing code, we must unlink it and
479 6bb70571 bellard
           all the potentially executing TB */
480 0e4b179d bellard
        cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
481 6bb70571 bellard
482 461c0471 bellard
        /* when a20 is changed, all the MMU mappings are invalid, so
483 461c0471 bellard
           we must flush everything */
484 1ac157da bellard
        tlb_flush(env, 1);
485 1ac157da bellard
        env->a20_mask = 0xffefffff | (a20_state << 20);
486 461c0471 bellard
    }
487 461c0471 bellard
}
488 461c0471 bellard
489 1ac157da bellard
void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
490 2c0262af bellard
{
491 1ac157da bellard
    int pe_state;
492 2c0262af bellard
493 b7f0f463 bellard
#if defined(DEBUG_MMU)
494 1ac157da bellard
    printf("CR0 update: CR0=0x%08x\n", new_cr0);
495 2c0262af bellard
#endif
496 1ac157da bellard
    if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
497 1ac157da bellard
        (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
498 1ac157da bellard
        tlb_flush(env, 1);
499 2c0262af bellard
    }
500 14ce26e7 bellard
501 14ce26e7 bellard
#ifdef TARGET_X86_64
502 14ce26e7 bellard
    if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
503 14ce26e7 bellard
        (env->efer & MSR_EFER_LME)) {
504 14ce26e7 bellard
        /* enter in long mode */
505 14ce26e7 bellard
        /* XXX: generate an exception */
506 14ce26e7 bellard
        if (!(env->cr[4] & CR4_PAE_MASK))
507 14ce26e7 bellard
            return;
508 14ce26e7 bellard
        env->efer |= MSR_EFER_LMA;
509 14ce26e7 bellard
        env->hflags |= HF_LMA_MASK;
510 14ce26e7 bellard
    } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
511 14ce26e7 bellard
               (env->efer & MSR_EFER_LMA)) {
512 14ce26e7 bellard
        /* exit long mode */
513 14ce26e7 bellard
        env->efer &= ~MSR_EFER_LMA;
514 14ce26e7 bellard
        env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
515 14ce26e7 bellard
        env->eip &= 0xffffffff;
516 14ce26e7 bellard
    }
517 14ce26e7 bellard
#endif
518 28c3ee3f bellard
    env->cr[0] = new_cr0 | CR0_ET_MASK;
519 5fafdf24 ths
   
520 436d8b89 bellard
    /* update PE flag in hidden flags */
521 436d8b89 bellard
    pe_state = (env->cr[0] & CR0_PE_MASK);
522 436d8b89 bellard
    env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
523 436d8b89 bellard
    /* ensure that ADDSEG is always set in real mode */
524 436d8b89 bellard
    env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
525 9588b95a bellard
    /* update FPU flags */
526 9588b95a bellard
    env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
527 9588b95a bellard
        ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
528 2c0262af bellard
}
529 2c0262af bellard
530 bf079a1e bellard
/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
531 bf079a1e bellard
   the PDPT */
532 14ce26e7 bellard
void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
533 2c0262af bellard
{
534 1ac157da bellard
    env->cr[3] = new_cr3;
535 2c0262af bellard
    if (env->cr[0] & CR0_PG_MASK) {
536 2c0262af bellard
#if defined(DEBUG_MMU)
537 14ce26e7 bellard
        printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
538 2c0262af bellard
#endif
539 1ac157da bellard
        tlb_flush(env, 0);
540 2c0262af bellard
    }
541 2c0262af bellard
}
542 2c0262af bellard
543 1ac157da bellard
void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
544 2c0262af bellard
{
545 1ac157da bellard
#if defined(DEBUG_MMU)
546 14ce26e7 bellard
    printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
547 1ac157da bellard
#endif
548 1ac157da bellard
    if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
549 1ac157da bellard
        (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
550 1ac157da bellard
        tlb_flush(env, 1);
551 1ac157da bellard
    }
552 664e0f19 bellard
    /* SSE handling */
553 664e0f19 bellard
    if (!(env->cpuid_features & CPUID_SSE))
554 664e0f19 bellard
        new_cr4 &= ~CR4_OSFXSR_MASK;
555 664e0f19 bellard
    if (new_cr4 & CR4_OSFXSR_MASK)
556 664e0f19 bellard
        env->hflags |= HF_OSFXSR_MASK;
557 664e0f19 bellard
    else
558 664e0f19 bellard
        env->hflags &= ~HF_OSFXSR_MASK;
559 664e0f19 bellard
560 1ac157da bellard
    env->cr[4] = new_cr4;
561 2c0262af bellard
}
562 2c0262af bellard
563 2c0262af bellard
/* XXX: also flush 4MB pages */
564 8f091a59 bellard
void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr)
565 2c0262af bellard
{
566 2c0262af bellard
    tlb_flush_page(env, addr);
567 2c0262af bellard
}
568 2c0262af bellard
569 5fafdf24 ths
#if defined(CONFIG_USER_ONLY)
570 14ce26e7 bellard
571 5fafdf24 ths
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
572 8df1cd07 bellard
                             int is_write, int is_user, int is_softmmu)
573 14ce26e7 bellard
{
574 8df1cd07 bellard
    /* user mode only emulation */
575 8df1cd07 bellard
    is_write &= 1;
576 8df1cd07 bellard
    env->cr[2] = addr;
577 8df1cd07 bellard
    env->error_code = (is_write << PG_ERROR_W_BIT);
578 8df1cd07 bellard
    env->error_code |= PG_ERROR_U_MASK;
579 54ca9095 bellard
    env->exception_index = EXCP0E_PAGE;
580 8df1cd07 bellard
    return 1;
581 14ce26e7 bellard
}
582 14ce26e7 bellard
583 9b3c35e0 j_mayer
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
584 14ce26e7 bellard
{
585 8df1cd07 bellard
    return addr;
586 14ce26e7 bellard
}
587 14ce26e7 bellard
588 8df1cd07 bellard
#else
589 8df1cd07 bellard
590 4b4f782c bellard
#define PHYS_ADDR_MASK 0xfffff000
591 4b4f782c bellard
592 2c0262af bellard
/* return value:
593 5fafdf24 ths
   -1 = cannot handle fault
594 5fafdf24 ths
   0  = nothing more to do
595 2c0262af bellard
   1  = generate PF fault
596 2c0262af bellard
   2  = soft MMU activation required for this block
597 2c0262af bellard
*/
598 5fafdf24 ths
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
599 4b4f782c bellard
                             int is_write1, int is_user, int is_softmmu)
600 2c0262af bellard
{
601 4b4f782c bellard
    uint64_t ptep, pte;
602 14ce26e7 bellard
    uint32_t pdpe_addr, pde_addr, pte_addr;
603 4b4f782c bellard
    int error_code, is_dirty, prot, page_size, ret, is_write;
604 14ce26e7 bellard
    unsigned long paddr, page_offset;
605 14ce26e7 bellard
    target_ulong vaddr, virt_addr;
606 5fafdf24 ths
   
607 436d8b89 bellard
#if defined(DEBUG_MMU)
608 5fafdf24 ths
    printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
609 4b4f782c bellard
           addr, is_write1, is_user, env->eip);
610 2c0262af bellard
#endif
611 4b4f782c bellard
    is_write = is_write1 & 1;
612 5fafdf24 ths
   
613 2c0262af bellard
    if (!(env->cr[0] & CR0_PG_MASK)) {
614 2c0262af bellard
        pte = addr;
615 461c0471 bellard
        virt_addr = addr & TARGET_PAGE_MASK;
616 4b4f782c bellard
        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
617 2c0262af bellard
        page_size = 4096;
618 2c0262af bellard
        goto do_mapping;
619 2c0262af bellard
    }
620 2c0262af bellard
621 14ce26e7 bellard
    if (env->cr[4] & CR4_PAE_MASK) {
622 4b4f782c bellard
        uint64_t pde, pdpe;
623 4b4f782c bellard
624 14ce26e7 bellard
        /* XXX: we only use 32 bit physical addresses */
625 14ce26e7 bellard
#ifdef TARGET_X86_64
626 14ce26e7 bellard
        if (env->hflags & HF_LMA_MASK) {
627 4b4f782c bellard
            uint32_t pml4e_addr;
628 4b4f782c bellard
            uint64_t pml4e;
629 14ce26e7 bellard
            int32_t sext;
630 14ce26e7 bellard
631 14ce26e7 bellard
            /* test virtual address sign extension */
632 14ce26e7 bellard
            sext = (int64_t)addr >> 47;
633 14ce26e7 bellard
            if (sext != 0 && sext != -1) {
634 54ca9095 bellard
                env->error_code = 0;
635 54ca9095 bellard
                env->exception_index = EXCP0D_GPF;
636 54ca9095 bellard
                return 1;
637 14ce26e7 bellard
            }
638 5fafdf24 ths
           
639 5fafdf24 ths
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
640 14ce26e7 bellard
                env->a20_mask;
641 4b4f782c bellard
            pml4e = ldq_phys(pml4e_addr);
642 14ce26e7 bellard
            if (!(pml4e & PG_PRESENT_MASK)) {
643 14ce26e7 bellard
                error_code = 0;
644 14ce26e7 bellard
                goto do_fault;
645 14ce26e7 bellard
            }
646 4b4f782c bellard
            if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
647 4b4f782c bellard
                error_code = PG_ERROR_RSVD_MASK;
648 4b4f782c bellard
                goto do_fault;
649 4b4f782c bellard
            }
650 14ce26e7 bellard
            if (!(pml4e & PG_ACCESSED_MASK)) {
651 14ce26e7 bellard
                pml4e |= PG_ACCESSED_MASK;
652 8df1cd07 bellard
                stl_phys_notdirty(pml4e_addr, pml4e);
653 14ce26e7 bellard
            }
654 4b4f782c bellard
            ptep = pml4e ^ PG_NX_MASK;
655 5fafdf24 ths
            pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
656 14ce26e7 bellard
                env->a20_mask;
657 4b4f782c bellard
            pdpe = ldq_phys(pdpe_addr);
658 14ce26e7 bellard
            if (!(pdpe & PG_PRESENT_MASK)) {
659 14ce26e7 bellard
                error_code = 0;
660 14ce26e7 bellard
                goto do_fault;
661 14ce26e7 bellard
            }
662 4b4f782c bellard
            if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
663 4b4f782c bellard
                error_code = PG_ERROR_RSVD_MASK;
664 4b4f782c bellard
                goto do_fault;
665 4b4f782c bellard
            }
666 4b4f782c bellard
            ptep &= pdpe ^ PG_NX_MASK;
667 14ce26e7 bellard
            if (!(pdpe & PG_ACCESSED_MASK)) {
668 14ce26e7 bellard
                pdpe |= PG_ACCESSED_MASK;
669 8df1cd07 bellard
                stl_phys_notdirty(pdpe_addr, pdpe);
670 14ce26e7 bellard
            }
671 4b4f782c bellard
        } else
672 14ce26e7 bellard
#endif
673 14ce26e7 bellard
        {
674 4b4f782c bellard
            /* XXX: load them when cr3 is loaded ? */
675 5fafdf24 ths
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
676 14ce26e7 bellard
                env->a20_mask;
677 4b4f782c bellard
            pdpe = ldq_phys(pdpe_addr);
678 14ce26e7 bellard
            if (!(pdpe & PG_PRESENT_MASK)) {
679 14ce26e7 bellard
                error_code = 0;
680 14ce26e7 bellard
                goto do_fault;
681 14ce26e7 bellard
            }
682 4b4f782c bellard
            ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
683 10f0e412 bellard
        }
684 14ce26e7 bellard
685 4b4f782c bellard
        pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
686 14ce26e7 bellard
            env->a20_mask;
687 4b4f782c bellard
        pde = ldq_phys(pde_addr);
688 14ce26e7 bellard
        if (!(pde & PG_PRESENT_MASK)) {
689 14ce26e7 bellard
            error_code = 0;
690 14ce26e7 bellard
            goto do_fault;
691 2c0262af bellard
        }
692 4b4f782c bellard
        if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
693 4b4f782c bellard
            error_code = PG_ERROR_RSVD_MASK;
694 4b4f782c bellard
            goto do_fault;
695 4b4f782c bellard
        }
696 4b4f782c bellard
        ptep &= pde ^ PG_NX_MASK;
697 14ce26e7 bellard
        if (pde & PG_PSE_MASK) {
698 14ce26e7 bellard
            /* 2 MB page */
699 14ce26e7 bellard
            page_size = 2048 * 1024;
700 4b4f782c bellard
            ptep ^= PG_NX_MASK;
701 4b4f782c bellard
            if ((ptep & PG_NX_MASK) && is_write1 == 2)
702 4b4f782c bellard
                goto do_fault_protect;
703 4b4f782c bellard
            if (is_user) {
704 4b4f782c bellard
                if (!(ptep & PG_USER_MASK))
705 4b4f782c bellard
                    goto do_fault_protect;
706 4b4f782c bellard
                if (is_write && !(ptep & PG_RW_MASK))
707 4b4f782c bellard
                    goto do_fault_protect;
708 4b4f782c bellard
            } else {
709 5fafdf24 ths
                if ((env->cr[0] & CR0_WP_MASK) &&
710 5fafdf24 ths
                    is_write && !(ptep & PG_RW_MASK))
711 4b4f782c bellard
                    goto do_fault_protect;
712 4b4f782c bellard
            }
713 4b4f782c bellard
            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
714 4b4f782c bellard
            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
715 4b4f782c bellard
                pde |= PG_ACCESSED_MASK;
716 4b4f782c bellard
                if (is_dirty)
717 4b4f782c bellard
                    pde |= PG_DIRTY_MASK;
718 4b4f782c bellard
                stl_phys_notdirty(pde_addr, pde);
719 4b4f782c bellard
            }
720 4b4f782c bellard
            /* align to page_size */
721 5fafdf24 ths
            pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
722 4b4f782c bellard
            virt_addr = addr & ~(page_size - 1);
723 14ce26e7 bellard
        } else {
724 14ce26e7 bellard
            /* 4 KB page */
725 14ce26e7 bellard
            if (!(pde & PG_ACCESSED_MASK)) {
726 14ce26e7 bellard
                pde |= PG_ACCESSED_MASK;
727 8df1cd07 bellard
                stl_phys_notdirty(pde_addr, pde);
728 14ce26e7 bellard
            }
729 4b4f782c bellard
            pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
730 14ce26e7 bellard
                env->a20_mask;
731 4b4f782c bellard
            pte = ldq_phys(pte_addr);
732 4b4f782c bellard
            if (!(pte & PG_PRESENT_MASK)) {
733 4b4f782c bellard
                error_code = 0;
734 4b4f782c bellard
                goto do_fault;
735 4b4f782c bellard
            }
736 4b4f782c bellard
            if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
737 4b4f782c bellard
                error_code = PG_ERROR_RSVD_MASK;
738 4b4f782c bellard
                goto do_fault;
739 4b4f782c bellard
            }
740 4b4f782c bellard
            /* combine pde and pte nx, user and rw protections */
741 4b4f782c bellard
            ptep &= pte ^ PG_NX_MASK;
742 4b4f782c bellard
            ptep ^= PG_NX_MASK;
743 4b4f782c bellard
            if ((ptep & PG_NX_MASK) && is_write1 == 2)
744 5fafdf24 ths
                goto do_fault_protect;
745 4b4f782c bellard
            if (is_user) {
746 4b4f782c bellard
                if (!(ptep & PG_USER_MASK))
747 4b4f782c bellard
                    goto do_fault_protect;
748 4b4f782c bellard
                if (is_write && !(ptep & PG_RW_MASK))
749 4b4f782c bellard
                    goto do_fault_protect;
750 4b4f782c bellard
            } else {
751 4b4f782c bellard
                if ((env->cr[0] & CR0_WP_MASK) &&
752 5fafdf24 ths
                    is_write && !(ptep & PG_RW_MASK))
753 4b4f782c bellard
                    goto do_fault_protect;
754 4b4f782c bellard
            }
755 4b4f782c bellard
            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
756 4b4f782c bellard
            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
757 4b4f782c bellard
                pte |= PG_ACCESSED_MASK;
758 4b4f782c bellard
                if (is_dirty)
759 4b4f782c bellard
                    pte |= PG_DIRTY_MASK;
760 4b4f782c bellard
                stl_phys_notdirty(pte_addr, pte);
761 4b4f782c bellard
            }
762 4b4f782c bellard
            page_size = 4096;
763 4b4f782c bellard
            virt_addr = addr & ~0xfff;
764 4b4f782c bellard
            pte = pte & (PHYS_ADDR_MASK | 0xfff);
765 2c0262af bellard
        }
766 14ce26e7 bellard
    } else {
767 4b4f782c bellard
        uint32_t pde;
768 4b4f782c bellard
769 2c0262af bellard
        /* page directory entry */
770 5fafdf24 ths
        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
771 14ce26e7 bellard
            env->a20_mask;
772 8df1cd07 bellard
        pde = ldl_phys(pde_addr);
773 14ce26e7 bellard
        if (!(pde & PG_PRESENT_MASK)) {
774 2c0262af bellard
            error_code = 0;
775 2c0262af bellard
            goto do_fault;
776 2c0262af bellard
        }
777 14ce26e7 bellard
        /* if PSE bit is set, then we use a 4MB page */
778 14ce26e7 bellard
        if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
779 14ce26e7 bellard
            page_size = 4096 * 1024;
780 14ce26e7 bellard
            if (is_user) {
781 14ce26e7 bellard
                if (!(pde & PG_USER_MASK))
782 14ce26e7 bellard
                    goto do_fault_protect;
783 14ce26e7 bellard
                if (is_write && !(pde & PG_RW_MASK))
784 14ce26e7 bellard
                    goto do_fault_protect;
785 14ce26e7 bellard
            } else {
786 5fafdf24 ths
                if ((env->cr[0] & CR0_WP_MASK) &&
787 5fafdf24 ths
                    is_write && !(pde & PG_RW_MASK))
788 14ce26e7 bellard
                    goto do_fault_protect;
789 14ce26e7 bellard
            }
790 14ce26e7 bellard
            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
791 14ce26e7 bellard
            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
792 14ce26e7 bellard
                pde |= PG_ACCESSED_MASK;
793 14ce26e7 bellard
                if (is_dirty)
794 14ce26e7 bellard
                    pde |= PG_DIRTY_MASK;
795 8df1cd07 bellard
                stl_phys_notdirty(pde_addr, pde);
796 14ce26e7 bellard
            }
797 5fafdf24 ths
       
798 14ce26e7 bellard
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
799 14ce26e7 bellard
            ptep = pte;
800 14ce26e7 bellard
            virt_addr = addr & ~(page_size - 1);
801 2c0262af bellard
        } else {
802 14ce26e7 bellard
            if (!(pde & PG_ACCESSED_MASK)) {
803 14ce26e7 bellard
                pde |= PG_ACCESSED_MASK;
804 8df1cd07 bellard
                stl_phys_notdirty(pde_addr, pde);
805 14ce26e7 bellard
            }
806 14ce26e7 bellard
807 14ce26e7 bellard
            /* page directory entry */
808 5fafdf24 ths
            pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
809 14ce26e7 bellard
                env->a20_mask;
810 8df1cd07 bellard
            pte = ldl_phys(pte_addr);
811 14ce26e7 bellard
            if (!(pte & PG_PRESENT_MASK)) {
812 14ce26e7 bellard
                error_code = 0;
813 14ce26e7 bellard
                goto do_fault;
814 14ce26e7 bellard
            }
815 14ce26e7 bellard
            /* combine pde and pte user and rw protections */
816 14ce26e7 bellard
            ptep = pte & pde;
817 14ce26e7 bellard
            if (is_user) {
818 14ce26e7 bellard
                if (!(ptep & PG_USER_MASK))
819 14ce26e7 bellard
                    goto do_fault_protect;
820 14ce26e7 bellard
                if (is_write && !(ptep & PG_RW_MASK))
821 14ce26e7 bellard
                    goto do_fault_protect;
822 14ce26e7 bellard
            } else {
823 14ce26e7 bellard
                if ((env->cr[0] & CR0_WP_MASK) &&
824 5fafdf24 ths
                    is_write && !(ptep & PG_RW_MASK))
825 14ce26e7 bellard
                    goto do_fault_protect;
826 14ce26e7 bellard
            }
827 14ce26e7 bellard
            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
828 14ce26e7 bellard
            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
829 14ce26e7 bellard
                pte |= PG_ACCESSED_MASK;
830 14ce26e7 bellard
                if (is_dirty)
831 14ce26e7 bellard
                    pte |= PG_DIRTY_MASK;
832 8df1cd07 bellard
                stl_phys_notdirty(pte_addr, pte);
833 14ce26e7 bellard
            }
834 14ce26e7 bellard
            page_size = 4096;
835 14ce26e7 bellard
            virt_addr = addr & ~0xfff;
836 2c0262af bellard
        }
837 4b4f782c bellard
    }
838 4b4f782c bellard
    /* the page can be put in the TLB */
839 4b4f782c bellard
    prot = PAGE_READ;
840 4b4f782c bellard
    if (!(ptep & PG_NX_MASK))
841 4b4f782c bellard
        prot |= PAGE_EXEC;
842 4b4f782c bellard
    if (pte & PG_DIRTY_MASK) {
843 4b4f782c bellard
        /* only set write access if already dirty... otherwise wait
844 4b4f782c bellard
           for dirty access */
845 4b4f782c bellard
        if (is_user) {
846 4b4f782c bellard
            if (ptep & PG_RW_MASK)
847 4b4f782c bellard
                prot |= PAGE_WRITE;
848 4b4f782c bellard
        } else {
849 4b4f782c bellard
            if (!(env->cr[0] & CR0_WP_MASK) ||
850 4b4f782c bellard
                (ptep & PG_RW_MASK))
851 4b4f782c bellard
                prot |= PAGE_WRITE;
852 c8135d9a bellard
        }
853 2c0262af bellard
    }
854 2c0262af bellard
 do_mapping:
855 1ac157da bellard
    pte = pte & env->a20_mask;
856 2c0262af bellard
857 436d8b89 bellard
    /* Even if 4MB pages, we map only one 4KB page in the cache to
858 436d8b89 bellard
       avoid filling it too fast */
859 436d8b89 bellard
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
860 436d8b89 bellard
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
861 436d8b89 bellard
    vaddr = virt_addr + page_offset;
862 5fafdf24 ths
   
863 4b4f782c bellard
    ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
864 2c0262af bellard
    return ret;
865 2c0262af bellard
 do_fault_protect:
866 2c0262af bellard
    error_code = PG_ERROR_P_MASK;
867 2c0262af bellard
 do_fault:
868 2c0262af bellard
    env->cr[2] = addr;
869 4b4f782c bellard
    error_code |= (is_write << PG_ERROR_W_BIT);
870 2c0262af bellard
    if (is_user)
871 4b4f782c bellard
        error_code |= PG_ERROR_U_MASK;
872 5fafdf24 ths
    if (is_write1 == 2 &&
873 5fafdf24 ths
        (env->efer & MSR_EFER_NXE) &&
874 4b4f782c bellard
        (env->cr[4] & CR4_PAE_MASK))
875 4b4f782c bellard
        error_code |= PG_ERROR_I_D_MASK;
876 4b4f782c bellard
    env->error_code = error_code;
877 54ca9095 bellard
    env->exception_index = EXCP0E_PAGE;
878 2c0262af bellard
    return 1;
879 2c0262af bellard
}
880 10f0e412 bellard
881 9b3c35e0 j_mayer
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
882 10f0e412 bellard
{
883 f51589da bellard
    uint32_t pde_addr, pte_addr;
884 10f0e412 bellard
    uint32_t pde, pte, paddr, page_offset, page_size;
885 10f0e412 bellard
886 f51589da bellard
    if (env->cr[4] & CR4_PAE_MASK) {
887 f51589da bellard
        uint32_t pdpe_addr, pde_addr, pte_addr;
888 f51589da bellard
        uint32_t pdpe;
889 f51589da bellard
890 f51589da bellard
        /* XXX: we only use 32 bit physical addresses */
891 f51589da bellard
#ifdef TARGET_X86_64
892 f51589da bellard
        if (env->hflags & HF_LMA_MASK) {
893 f51589da bellard
            uint32_t pml4e_addr, pml4e;
894 f51589da bellard
            int32_t sext;
895 f51589da bellard
896 f51589da bellard
            /* test virtual address sign extension */
897 f51589da bellard
            sext = (int64_t)addr >> 47;
898 f51589da bellard
            if (sext != 0 && sext != -1)
899 f51589da bellard
                return -1;
900 5fafdf24 ths
           
901 5fafdf24 ths
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
902 f51589da bellard
                env->a20_mask;
903 8df1cd07 bellard
            pml4e = ldl_phys(pml4e_addr);
904 f51589da bellard
            if (!(pml4e & PG_PRESENT_MASK))
905 f51589da bellard
                return -1;
906 5fafdf24 ths
           
907 5fafdf24 ths
            pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
908 f51589da bellard
                env->a20_mask;
909 8df1cd07 bellard
            pdpe = ldl_phys(pdpe_addr);
910 f51589da bellard
            if (!(pdpe & PG_PRESENT_MASK))
911 f51589da bellard
                return -1;
912 5fafdf24 ths
        } else
913 f51589da bellard
#endif
914 f51589da bellard
        {
915 5fafdf24 ths
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
916 f51589da bellard
                env->a20_mask;
917 8df1cd07 bellard
            pdpe = ldl_phys(pdpe_addr);
918 f51589da bellard
            if (!(pdpe & PG_PRESENT_MASK))
919 f51589da bellard
                return -1;
920 f51589da bellard
        }
921 f51589da bellard
922 f51589da bellard
        pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
923 f51589da bellard
            env->a20_mask;
924 8df1cd07 bellard
        pde = ldl_phys(pde_addr);
925 f51589da bellard
        if (!(pde & PG_PRESENT_MASK)) {
926 10f0e412 bellard
            return -1;
927 f51589da bellard
        }
928 f51589da bellard
        if (pde & PG_PSE_MASK) {
929 f51589da bellard
            /* 2 MB page */
930 f51589da bellard
            page_size = 2048 * 1024;
931 f51589da bellard
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
932 f51589da bellard
        } else {
933 f51589da bellard
            /* 4 KB page */
934 f51589da bellard
            pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
935 f51589da bellard
                env->a20_mask;
936 f51589da bellard
            page_size = 4096;
937 8df1cd07 bellard
            pte = ldl_phys(pte_addr);
938 f51589da bellard
        }
939 f51589da bellard
    } else {
940 f51589da bellard
        if (!(env->cr[0] & CR0_PG_MASK)) {
941 f51589da bellard
            pte = addr;
942 f51589da bellard
            page_size = 4096;
943 10f0e412 bellard
        } else {
944 10f0e412 bellard
            /* page directory entry */
945 af661ad1 ths
            pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
946 8df1cd07 bellard
            pde = ldl_phys(pde_addr);
947 5fafdf24 ths
            if (!(pde & PG_PRESENT_MASK))
948 10f0e412 bellard
                return -1;
949 f51589da bellard
            if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
950 f51589da bellard
                pte = pde & ~0x003ff000; /* align to 4MB */
951 f51589da bellard
                page_size = 4096 * 1024;
952 f51589da bellard
            } else {
953 f51589da bellard
                /* page directory entry */
954 f51589da bellard
                pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
955 8df1cd07 bellard
                pte = ldl_phys(pte_addr);
956 f51589da bellard
                if (!(pte & PG_PRESENT_MASK))
957 f51589da bellard
                    return -1;
958 f51589da bellard
                page_size = 4096;
959 f51589da bellard
            }
960 10f0e412 bellard
        }
961 f51589da bellard
        pte = pte & env->a20_mask;
962 10f0e412 bellard
    }
963 f51589da bellard
964 10f0e412 bellard
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
965 10f0e412 bellard
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
966 10f0e412 bellard
    return paddr;
967 10f0e412 bellard
}
968 8df1cd07 bellard
#endif /* !CONFIG_USER_ONLY */
969 9588b95a bellard
970 9588b95a bellard
#if defined(USE_CODE_COPY)
971 9588b95a bellard
struct fpstate {
972 9588b95a bellard
    uint16_t fpuc;
973 9588b95a bellard
    uint16_t dummy1;
974 9588b95a bellard
    uint16_t fpus;
975 9588b95a bellard
    uint16_t dummy2;
976 9588b95a bellard
    uint16_t fptag;
977 9588b95a bellard
    uint16_t dummy3;
978 9588b95a bellard
979 9588b95a bellard
    uint32_t fpip;
980 9588b95a bellard
    uint32_t fpcs;
981 9588b95a bellard
    uint32_t fpoo;
982 9588b95a bellard
    uint32_t fpos;
983 9588b95a bellard
    uint8_t fpregs1[8 * 10];
984 9588b95a bellard
};
985 9588b95a bellard
986 9588b95a bellard
void restore_native_fp_state(CPUState *env)
987 9588b95a bellard
{
988 9588b95a bellard
    int fptag, i, j;
989 9588b95a bellard
    struct fpstate fp1, *fp = &fp1;
990 5fafdf24 ths
   
991 9588b95a bellard
    fp->fpuc = env->fpuc;
992 9588b95a bellard
    fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
993 9588b95a bellard
    fptag = 0;
994 9588b95a bellard
    for (i=7; i>=0; i--) {
995 9588b95a bellard
        fptag <<= 2;
996 9588b95a bellard
        if (env->fptags[i]) {
997 9588b95a bellard
            fptag |= 3;
998 9588b95a bellard
        } else {
999 9588b95a bellard
            /* the FPU automatically computes it */
1000 9588b95a bellard
        }
1001 9588b95a bellard
    }
1002 9588b95a bellard
    fp->fptag = fptag;
1003 9588b95a bellard
    j = env->fpstt;
1004 9588b95a bellard
    for(i = 0;i < 8; i++) {
1005 664e0f19 bellard
        memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
1006 9588b95a bellard
        j = (j + 1) & 7;
1007 9588b95a bellard
    }
1008 9588b95a bellard
    asm volatile ("frstor %0" : "=m" (*fp));
1009 9588b95a bellard
    env->native_fp_regs = 1;
1010 9588b95a bellard
}
1011 5fafdf24 ths
1012 9588b95a bellard
void save_native_fp_state(CPUState *env)
1013 9588b95a bellard
{
1014 9588b95a bellard
    int fptag, i, j;
1015 9588b95a bellard
    uint16_t fpuc;
1016 9588b95a bellard
    struct fpstate fp1, *fp = &fp1;
1017 9588b95a bellard
1018 9588b95a bellard
    asm volatile ("fsave %0" : : "m" (*fp));
1019 9588b95a bellard
    env->fpuc = fp->fpuc;
1020 9588b95a bellard
    env->fpstt = (fp->fpus >> 11) & 7;
1021 9588b95a bellard
    env->fpus = fp->fpus & ~0x3800;
1022 9588b95a bellard
    fptag = fp->fptag;
1023 9588b95a bellard
    for(i = 0;i < 8; i++) {
1024 9588b95a bellard
        env->fptags[i] = ((fptag & 3) == 3);
1025 9588b95a bellard
        fptag >>= 2;
1026 9588b95a bellard
    }
1027 9588b95a bellard
    j = env->fpstt;
1028 9588b95a bellard
    for(i = 0;i < 8; i++) {
1029 664e0f19 bellard
        memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
1030 9588b95a bellard
        j = (j + 1) & 7;
1031 9588b95a bellard
    }
1032 9588b95a bellard
    /* we must restore the default rounding state */
1033 9588b95a bellard
    /* XXX: we do not restore the exception state */
1034 9588b95a bellard
    fpuc = 0x037f | (env->fpuc & (3 << 10));
1035 9588b95a bellard
    asm volatile("fldcw %0" : : "m" (fpuc));
1036 9588b95a bellard
    env->native_fp_regs = 0;
1037 9588b95a bellard
}
1038 9588b95a bellard
#endif