Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ cb33da57

History | View | Annotate | Download (32.8 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 8df1cd07 bellard
                             int is_write, int is_user, 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 4b4f782c bellard
                             int is_write1, int is_user, 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 4b4f782c bellard
    int error_code, is_dirty, prot, page_size, ret, is_write;
606 14ce26e7 bellard
    unsigned long paddr, page_offset;
607 14ce26e7 bellard
    target_ulong vaddr, virt_addr;
608 3b46e624 ths
609 436d8b89 bellard
#if defined(DEBUG_MMU)
610 5fafdf24 ths
    printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
611 4b4f782c bellard
           addr, is_write1, is_user, env->eip);
612 2c0262af bellard
#endif
613 4b4f782c bellard
    is_write = is_write1 & 1;
614 3b46e624 ths
615 2c0262af bellard
    if (!(env->cr[0] & CR0_PG_MASK)) {
616 2c0262af bellard
        pte = addr;
617 461c0471 bellard
        virt_addr = addr & TARGET_PAGE_MASK;
618 4b4f782c bellard
        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
619 2c0262af bellard
        page_size = 4096;
620 2c0262af bellard
        goto do_mapping;
621 2c0262af bellard
    }
622 2c0262af bellard
623 14ce26e7 bellard
    if (env->cr[4] & CR4_PAE_MASK) {
624 4b4f782c bellard
        uint64_t pde, pdpe;
625 4b4f782c bellard
626 14ce26e7 bellard
        /* XXX: we only use 32 bit physical addresses */
627 14ce26e7 bellard
#ifdef TARGET_X86_64
628 14ce26e7 bellard
        if (env->hflags & HF_LMA_MASK) {
629 4b4f782c bellard
            uint32_t pml4e_addr;
630 4b4f782c bellard
            uint64_t pml4e;
631 14ce26e7 bellard
            int32_t sext;
632 14ce26e7 bellard
633 14ce26e7 bellard
            /* test virtual address sign extension */
634 14ce26e7 bellard
            sext = (int64_t)addr >> 47;
635 14ce26e7 bellard
            if (sext != 0 && sext != -1) {
636 54ca9095 bellard
                env->error_code = 0;
637 54ca9095 bellard
                env->exception_index = EXCP0D_GPF;
638 54ca9095 bellard
                return 1;
639 14ce26e7 bellard
            }
640 3b46e624 ths
641 5fafdf24 ths
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
642 14ce26e7 bellard
                env->a20_mask;
643 4b4f782c bellard
            pml4e = ldq_phys(pml4e_addr);
644 14ce26e7 bellard
            if (!(pml4e & PG_PRESENT_MASK)) {
645 14ce26e7 bellard
                error_code = 0;
646 14ce26e7 bellard
                goto do_fault;
647 14ce26e7 bellard
            }
648 4b4f782c bellard
            if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
649 4b4f782c bellard
                error_code = PG_ERROR_RSVD_MASK;
650 4b4f782c bellard
                goto do_fault;
651 4b4f782c bellard
            }
652 14ce26e7 bellard
            if (!(pml4e & PG_ACCESSED_MASK)) {
653 14ce26e7 bellard
                pml4e |= PG_ACCESSED_MASK;
654 8df1cd07 bellard
                stl_phys_notdirty(pml4e_addr, pml4e);
655 14ce26e7 bellard
            }
656 4b4f782c bellard
            ptep = pml4e ^ PG_NX_MASK;
657 5fafdf24 ths
            pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
658 14ce26e7 bellard
                env->a20_mask;
659 4b4f782c bellard
            pdpe = ldq_phys(pdpe_addr);
660 14ce26e7 bellard
            if (!(pdpe & PG_PRESENT_MASK)) {
661 14ce26e7 bellard
                error_code = 0;
662 14ce26e7 bellard
                goto do_fault;
663 14ce26e7 bellard
            }
664 4b4f782c bellard
            if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
665 4b4f782c bellard
                error_code = PG_ERROR_RSVD_MASK;
666 4b4f782c bellard
                goto do_fault;
667 4b4f782c bellard
            }
668 4b4f782c bellard
            ptep &= pdpe ^ PG_NX_MASK;
669 14ce26e7 bellard
            if (!(pdpe & PG_ACCESSED_MASK)) {
670 14ce26e7 bellard
                pdpe |= PG_ACCESSED_MASK;
671 8df1cd07 bellard
                stl_phys_notdirty(pdpe_addr, pdpe);
672 14ce26e7 bellard
            }
673 4b4f782c bellard
        } else
674 14ce26e7 bellard
#endif
675 14ce26e7 bellard
        {
676 4b4f782c bellard
            /* XXX: load them when cr3 is loaded ? */
677 5fafdf24 ths
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
678 14ce26e7 bellard
                env->a20_mask;
679 4b4f782c bellard
            pdpe = ldq_phys(pdpe_addr);
680 14ce26e7 bellard
            if (!(pdpe & PG_PRESENT_MASK)) {
681 14ce26e7 bellard
                error_code = 0;
682 14ce26e7 bellard
                goto do_fault;
683 14ce26e7 bellard
            }
684 4b4f782c bellard
            ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
685 10f0e412 bellard
        }
686 14ce26e7 bellard
687 4b4f782c bellard
        pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
688 14ce26e7 bellard
            env->a20_mask;
689 4b4f782c bellard
        pde = ldq_phys(pde_addr);
690 14ce26e7 bellard
        if (!(pde & PG_PRESENT_MASK)) {
691 14ce26e7 bellard
            error_code = 0;
692 14ce26e7 bellard
            goto do_fault;
693 2c0262af bellard
        }
694 4b4f782c bellard
        if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
695 4b4f782c bellard
            error_code = PG_ERROR_RSVD_MASK;
696 4b4f782c bellard
            goto do_fault;
697 4b4f782c bellard
        }
698 4b4f782c bellard
        ptep &= pde ^ PG_NX_MASK;
699 14ce26e7 bellard
        if (pde & PG_PSE_MASK) {
700 14ce26e7 bellard
            /* 2 MB page */
701 14ce26e7 bellard
            page_size = 2048 * 1024;
702 4b4f782c bellard
            ptep ^= PG_NX_MASK;
703 4b4f782c bellard
            if ((ptep & PG_NX_MASK) && is_write1 == 2)
704 4b4f782c bellard
                goto do_fault_protect;
705 4b4f782c bellard
            if (is_user) {
706 4b4f782c bellard
                if (!(ptep & PG_USER_MASK))
707 4b4f782c bellard
                    goto do_fault_protect;
708 4b4f782c bellard
                if (is_write && !(ptep & PG_RW_MASK))
709 4b4f782c bellard
                    goto do_fault_protect;
710 4b4f782c bellard
            } else {
711 5fafdf24 ths
                if ((env->cr[0] & CR0_WP_MASK) &&
712 5fafdf24 ths
                    is_write && !(ptep & PG_RW_MASK))
713 4b4f782c bellard
                    goto do_fault_protect;
714 4b4f782c bellard
            }
715 4b4f782c bellard
            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
716 4b4f782c bellard
            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
717 4b4f782c bellard
                pde |= PG_ACCESSED_MASK;
718 4b4f782c bellard
                if (is_dirty)
719 4b4f782c bellard
                    pde |= PG_DIRTY_MASK;
720 4b4f782c bellard
                stl_phys_notdirty(pde_addr, pde);
721 4b4f782c bellard
            }
722 4b4f782c bellard
            /* align to page_size */
723 5fafdf24 ths
            pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
724 4b4f782c bellard
            virt_addr = addr & ~(page_size - 1);
725 14ce26e7 bellard
        } else {
726 14ce26e7 bellard
            /* 4 KB page */
727 14ce26e7 bellard
            if (!(pde & PG_ACCESSED_MASK)) {
728 14ce26e7 bellard
                pde |= PG_ACCESSED_MASK;
729 8df1cd07 bellard
                stl_phys_notdirty(pde_addr, pde);
730 14ce26e7 bellard
            }
731 4b4f782c bellard
            pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
732 14ce26e7 bellard
                env->a20_mask;
733 4b4f782c bellard
            pte = ldq_phys(pte_addr);
734 4b4f782c bellard
            if (!(pte & PG_PRESENT_MASK)) {
735 4b4f782c bellard
                error_code = 0;
736 4b4f782c bellard
                goto do_fault;
737 4b4f782c bellard
            }
738 4b4f782c bellard
            if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
739 4b4f782c bellard
                error_code = PG_ERROR_RSVD_MASK;
740 4b4f782c bellard
                goto do_fault;
741 4b4f782c bellard
            }
742 4b4f782c bellard
            /* combine pde and pte nx, user and rw protections */
743 4b4f782c bellard
            ptep &= pte ^ PG_NX_MASK;
744 4b4f782c bellard
            ptep ^= PG_NX_MASK;
745 4b4f782c bellard
            if ((ptep & PG_NX_MASK) && is_write1 == 2)
746 5fafdf24 ths
                goto do_fault_protect;
747 4b4f782c bellard
            if (is_user) {
748 4b4f782c bellard
                if (!(ptep & PG_USER_MASK))
749 4b4f782c bellard
                    goto do_fault_protect;
750 4b4f782c bellard
                if (is_write && !(ptep & PG_RW_MASK))
751 4b4f782c bellard
                    goto do_fault_protect;
752 4b4f782c bellard
            } else {
753 4b4f782c bellard
                if ((env->cr[0] & CR0_WP_MASK) &&
754 5fafdf24 ths
                    is_write && !(ptep & PG_RW_MASK))
755 4b4f782c bellard
                    goto do_fault_protect;
756 4b4f782c bellard
            }
757 4b4f782c bellard
            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
758 4b4f782c bellard
            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
759 4b4f782c bellard
                pte |= PG_ACCESSED_MASK;
760 4b4f782c bellard
                if (is_dirty)
761 4b4f782c bellard
                    pte |= PG_DIRTY_MASK;
762 4b4f782c bellard
                stl_phys_notdirty(pte_addr, pte);
763 4b4f782c bellard
            }
764 4b4f782c bellard
            page_size = 4096;
765 4b4f782c bellard
            virt_addr = addr & ~0xfff;
766 4b4f782c bellard
            pte = pte & (PHYS_ADDR_MASK | 0xfff);
767 2c0262af bellard
        }
768 14ce26e7 bellard
    } else {
769 4b4f782c bellard
        uint32_t pde;
770 4b4f782c bellard
771 2c0262af bellard
        /* page directory entry */
772 5fafdf24 ths
        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
773 14ce26e7 bellard
            env->a20_mask;
774 8df1cd07 bellard
        pde = ldl_phys(pde_addr);
775 14ce26e7 bellard
        if (!(pde & PG_PRESENT_MASK)) {
776 2c0262af bellard
            error_code = 0;
777 2c0262af bellard
            goto do_fault;
778 2c0262af bellard
        }
779 14ce26e7 bellard
        /* if PSE bit is set, then we use a 4MB page */
780 14ce26e7 bellard
        if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
781 14ce26e7 bellard
            page_size = 4096 * 1024;
782 14ce26e7 bellard
            if (is_user) {
783 14ce26e7 bellard
                if (!(pde & PG_USER_MASK))
784 14ce26e7 bellard
                    goto do_fault_protect;
785 14ce26e7 bellard
                if (is_write && !(pde & PG_RW_MASK))
786 14ce26e7 bellard
                    goto do_fault_protect;
787 14ce26e7 bellard
            } else {
788 5fafdf24 ths
                if ((env->cr[0] & CR0_WP_MASK) &&
789 5fafdf24 ths
                    is_write && !(pde & PG_RW_MASK))
790 14ce26e7 bellard
                    goto do_fault_protect;
791 14ce26e7 bellard
            }
792 14ce26e7 bellard
            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
793 14ce26e7 bellard
            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
794 14ce26e7 bellard
                pde |= PG_ACCESSED_MASK;
795 14ce26e7 bellard
                if (is_dirty)
796 14ce26e7 bellard
                    pde |= PG_DIRTY_MASK;
797 8df1cd07 bellard
                stl_phys_notdirty(pde_addr, pde);
798 14ce26e7 bellard
            }
799 3b46e624 ths
800 14ce26e7 bellard
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
801 14ce26e7 bellard
            ptep = pte;
802 14ce26e7 bellard
            virt_addr = addr & ~(page_size - 1);
803 2c0262af bellard
        } else {
804 14ce26e7 bellard
            if (!(pde & PG_ACCESSED_MASK)) {
805 14ce26e7 bellard
                pde |= PG_ACCESSED_MASK;
806 8df1cd07 bellard
                stl_phys_notdirty(pde_addr, pde);
807 14ce26e7 bellard
            }
808 14ce26e7 bellard
809 14ce26e7 bellard
            /* page directory entry */
810 5fafdf24 ths
            pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
811 14ce26e7 bellard
                env->a20_mask;
812 8df1cd07 bellard
            pte = ldl_phys(pte_addr);
813 14ce26e7 bellard
            if (!(pte & PG_PRESENT_MASK)) {
814 14ce26e7 bellard
                error_code = 0;
815 14ce26e7 bellard
                goto do_fault;
816 14ce26e7 bellard
            }
817 14ce26e7 bellard
            /* combine pde and pte user and rw protections */
818 14ce26e7 bellard
            ptep = pte & pde;
819 14ce26e7 bellard
            if (is_user) {
820 14ce26e7 bellard
                if (!(ptep & PG_USER_MASK))
821 14ce26e7 bellard
                    goto do_fault_protect;
822 14ce26e7 bellard
                if (is_write && !(ptep & PG_RW_MASK))
823 14ce26e7 bellard
                    goto do_fault_protect;
824 14ce26e7 bellard
            } else {
825 14ce26e7 bellard
                if ((env->cr[0] & CR0_WP_MASK) &&
826 5fafdf24 ths
                    is_write && !(ptep & PG_RW_MASK))
827 14ce26e7 bellard
                    goto do_fault_protect;
828 14ce26e7 bellard
            }
829 14ce26e7 bellard
            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
830 14ce26e7 bellard
            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
831 14ce26e7 bellard
                pte |= PG_ACCESSED_MASK;
832 14ce26e7 bellard
                if (is_dirty)
833 14ce26e7 bellard
                    pte |= PG_DIRTY_MASK;
834 8df1cd07 bellard
                stl_phys_notdirty(pte_addr, pte);
835 14ce26e7 bellard
            }
836 14ce26e7 bellard
            page_size = 4096;
837 14ce26e7 bellard
            virt_addr = addr & ~0xfff;
838 2c0262af bellard
        }
839 4b4f782c bellard
    }
840 4b4f782c bellard
    /* the page can be put in the TLB */
841 4b4f782c bellard
    prot = PAGE_READ;
842 4b4f782c bellard
    if (!(ptep & PG_NX_MASK))
843 4b4f782c bellard
        prot |= PAGE_EXEC;
844 4b4f782c bellard
    if (pte & PG_DIRTY_MASK) {
845 4b4f782c bellard
        /* only set write access if already dirty... otherwise wait
846 4b4f782c bellard
           for dirty access */
847 4b4f782c bellard
        if (is_user) {
848 4b4f782c bellard
            if (ptep & PG_RW_MASK)
849 4b4f782c bellard
                prot |= PAGE_WRITE;
850 4b4f782c bellard
        } else {
851 4b4f782c bellard
            if (!(env->cr[0] & CR0_WP_MASK) ||
852 4b4f782c bellard
                (ptep & PG_RW_MASK))
853 4b4f782c bellard
                prot |= PAGE_WRITE;
854 c8135d9a bellard
        }
855 2c0262af bellard
    }
856 2c0262af bellard
 do_mapping:
857 1ac157da bellard
    pte = pte & env->a20_mask;
858 2c0262af bellard
859 436d8b89 bellard
    /* Even if 4MB pages, we map only one 4KB page in the cache to
860 436d8b89 bellard
       avoid filling it too fast */
861 436d8b89 bellard
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
862 436d8b89 bellard
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
863 436d8b89 bellard
    vaddr = virt_addr + page_offset;
864 3b46e624 ths
865 4b4f782c bellard
    ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
866 2c0262af bellard
    return ret;
867 2c0262af bellard
 do_fault_protect:
868 2c0262af bellard
    error_code = PG_ERROR_P_MASK;
869 2c0262af bellard
 do_fault:
870 4b4f782c bellard
    error_code |= (is_write << PG_ERROR_W_BIT);
871 2c0262af bellard
    if (is_user)
872 4b4f782c bellard
        error_code |= PG_ERROR_U_MASK;
873 5fafdf24 ths
    if (is_write1 == 2 &&
874 5fafdf24 ths
        (env->efer & MSR_EFER_NXE) &&
875 4b4f782c bellard
        (env->cr[4] & CR4_PAE_MASK))
876 4b4f782c bellard
        error_code |= PG_ERROR_I_D_MASK;
877 0573fbfc ths
    if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE)) {
878 0573fbfc ths
        stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), addr);
879 0573fbfc ths
    } else {
880 0573fbfc ths
        env->cr[2] = addr;
881 0573fbfc ths
    }
882 4b4f782c bellard
    env->error_code = error_code;
883 54ca9095 bellard
    env->exception_index = EXCP0E_PAGE;
884 0573fbfc ths
    /* the VMM will handle this */
885 0573fbfc ths
    if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE))
886 0573fbfc ths
        return 2;
887 2c0262af bellard
    return 1;
888 2c0262af bellard
}
889 10f0e412 bellard
890 9b3c35e0 j_mayer
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
891 10f0e412 bellard
{
892 f51589da bellard
    uint32_t pde_addr, pte_addr;
893 10f0e412 bellard
    uint32_t pde, pte, paddr, page_offset, page_size;
894 10f0e412 bellard
895 f51589da bellard
    if (env->cr[4] & CR4_PAE_MASK) {
896 f51589da bellard
        uint32_t pdpe_addr, pde_addr, pte_addr;
897 f51589da bellard
        uint32_t pdpe;
898 f51589da bellard
899 f51589da bellard
        /* XXX: we only use 32 bit physical addresses */
900 f51589da bellard
#ifdef TARGET_X86_64
901 f51589da bellard
        if (env->hflags & HF_LMA_MASK) {
902 f51589da bellard
            uint32_t pml4e_addr, pml4e;
903 f51589da bellard
            int32_t sext;
904 f51589da bellard
905 f51589da bellard
            /* test virtual address sign extension */
906 f51589da bellard
            sext = (int64_t)addr >> 47;
907 f51589da bellard
            if (sext != 0 && sext != -1)
908 f51589da bellard
                return -1;
909 3b46e624 ths
910 5fafdf24 ths
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
911 f51589da bellard
                env->a20_mask;
912 8df1cd07 bellard
            pml4e = ldl_phys(pml4e_addr);
913 f51589da bellard
            if (!(pml4e & PG_PRESENT_MASK))
914 f51589da bellard
                return -1;
915 3b46e624 ths
916 5fafdf24 ths
            pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
917 f51589da bellard
                env->a20_mask;
918 8df1cd07 bellard
            pdpe = ldl_phys(pdpe_addr);
919 f51589da bellard
            if (!(pdpe & PG_PRESENT_MASK))
920 f51589da bellard
                return -1;
921 5fafdf24 ths
        } else
922 f51589da bellard
#endif
923 f51589da bellard
        {
924 5fafdf24 ths
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
925 f51589da bellard
                env->a20_mask;
926 8df1cd07 bellard
            pdpe = ldl_phys(pdpe_addr);
927 f51589da bellard
            if (!(pdpe & PG_PRESENT_MASK))
928 f51589da bellard
                return -1;
929 f51589da bellard
        }
930 f51589da bellard
931 f51589da bellard
        pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
932 f51589da bellard
            env->a20_mask;
933 8df1cd07 bellard
        pde = ldl_phys(pde_addr);
934 f51589da bellard
        if (!(pde & PG_PRESENT_MASK)) {
935 10f0e412 bellard
            return -1;
936 f51589da bellard
        }
937 f51589da bellard
        if (pde & PG_PSE_MASK) {
938 f51589da bellard
            /* 2 MB page */
939 f51589da bellard
            page_size = 2048 * 1024;
940 f51589da bellard
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
941 f51589da bellard
        } else {
942 f51589da bellard
            /* 4 KB page */
943 f51589da bellard
            pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
944 f51589da bellard
                env->a20_mask;
945 f51589da bellard
            page_size = 4096;
946 8df1cd07 bellard
            pte = ldl_phys(pte_addr);
947 f51589da bellard
        }
948 f51589da bellard
    } else {
949 f51589da bellard
        if (!(env->cr[0] & CR0_PG_MASK)) {
950 f51589da bellard
            pte = addr;
951 f51589da bellard
            page_size = 4096;
952 10f0e412 bellard
        } else {
953 10f0e412 bellard
            /* page directory entry */
954 af661ad1 ths
            pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
955 8df1cd07 bellard
            pde = ldl_phys(pde_addr);
956 5fafdf24 ths
            if (!(pde & PG_PRESENT_MASK))
957 10f0e412 bellard
                return -1;
958 f51589da bellard
            if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
959 f51589da bellard
                pte = pde & ~0x003ff000; /* align to 4MB */
960 f51589da bellard
                page_size = 4096 * 1024;
961 f51589da bellard
            } else {
962 f51589da bellard
                /* page directory entry */
963 f51589da bellard
                pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
964 8df1cd07 bellard
                pte = ldl_phys(pte_addr);
965 f51589da bellard
                if (!(pte & PG_PRESENT_MASK))
966 f51589da bellard
                    return -1;
967 f51589da bellard
                page_size = 4096;
968 f51589da bellard
            }
969 10f0e412 bellard
        }
970 f51589da bellard
        pte = pte & env->a20_mask;
971 10f0e412 bellard
    }
972 f51589da bellard
973 10f0e412 bellard
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
974 10f0e412 bellard
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
975 10f0e412 bellard
    return paddr;
976 10f0e412 bellard
}
977 8df1cd07 bellard
#endif /* !CONFIG_USER_ONLY */
978 9588b95a bellard
979 9588b95a bellard
#if defined(USE_CODE_COPY)
980 9588b95a bellard
struct fpstate {
981 9588b95a bellard
    uint16_t fpuc;
982 9588b95a bellard
    uint16_t dummy1;
983 9588b95a bellard
    uint16_t fpus;
984 9588b95a bellard
    uint16_t dummy2;
985 9588b95a bellard
    uint16_t fptag;
986 9588b95a bellard
    uint16_t dummy3;
987 9588b95a bellard
988 9588b95a bellard
    uint32_t fpip;
989 9588b95a bellard
    uint32_t fpcs;
990 9588b95a bellard
    uint32_t fpoo;
991 9588b95a bellard
    uint32_t fpos;
992 9588b95a bellard
    uint8_t fpregs1[8 * 10];
993 9588b95a bellard
};
994 9588b95a bellard
995 9588b95a bellard
void restore_native_fp_state(CPUState *env)
996 9588b95a bellard
{
997 9588b95a bellard
    int fptag, i, j;
998 9588b95a bellard
    struct fpstate fp1, *fp = &fp1;
999 3b46e624 ths
1000 9588b95a bellard
    fp->fpuc = env->fpuc;
1001 9588b95a bellard
    fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
1002 9588b95a bellard
    fptag = 0;
1003 9588b95a bellard
    for (i=7; i>=0; i--) {
1004 9588b95a bellard
        fptag <<= 2;
1005 9588b95a bellard
        if (env->fptags[i]) {
1006 9588b95a bellard
            fptag |= 3;
1007 9588b95a bellard
        } else {
1008 9588b95a bellard
            /* the FPU automatically computes it */
1009 9588b95a bellard
        }
1010 9588b95a bellard
    }
1011 9588b95a bellard
    fp->fptag = fptag;
1012 9588b95a bellard
    j = env->fpstt;
1013 9588b95a bellard
    for(i = 0;i < 8; i++) {
1014 664e0f19 bellard
        memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
1015 9588b95a bellard
        j = (j + 1) & 7;
1016 9588b95a bellard
    }
1017 9588b95a bellard
    asm volatile ("frstor %0" : "=m" (*fp));
1018 9588b95a bellard
    env->native_fp_regs = 1;
1019 9588b95a bellard
}
1020 5fafdf24 ths
1021 9588b95a bellard
void save_native_fp_state(CPUState *env)
1022 9588b95a bellard
{
1023 9588b95a bellard
    int fptag, i, j;
1024 9588b95a bellard
    uint16_t fpuc;
1025 9588b95a bellard
    struct fpstate fp1, *fp = &fp1;
1026 9588b95a bellard
1027 9588b95a bellard
    asm volatile ("fsave %0" : : "m" (*fp));
1028 9588b95a bellard
    env->fpuc = fp->fpuc;
1029 9588b95a bellard
    env->fpstt = (fp->fpus >> 11) & 7;
1030 9588b95a bellard
    env->fpus = fp->fpus & ~0x3800;
1031 9588b95a bellard
    fptag = fp->fptag;
1032 9588b95a bellard
    for(i = 0;i < 8; i++) {
1033 9588b95a bellard
        env->fptags[i] = ((fptag & 3) == 3);
1034 9588b95a bellard
        fptag >>= 2;
1035 9588b95a bellard
    }
1036 9588b95a bellard
    j = env->fpstt;
1037 9588b95a bellard
    for(i = 0;i < 8; i++) {
1038 664e0f19 bellard
        memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
1039 9588b95a bellard
        j = (j + 1) & 7;
1040 9588b95a bellard
    }
1041 9588b95a bellard
    /* we must restore the default rounding state */
1042 9588b95a bellard
    /* XXX: we do not restore the exception state */
1043 9588b95a bellard
    fpuc = 0x037f | (env->fpuc & (3 << 10));
1044 9588b95a bellard
    asm volatile("fldcw %0" : : "m" (fpuc));
1045 9588b95a bellard
    env->native_fp_regs = 0;
1046 9588b95a bellard
}
1047 9588b95a bellard
#endif