Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ ad848875

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