Statistics
| Branch: | Revision:

root / target-i386 / helper.c @ f8ed7070

History | View | Annotate | Download (39.1 kB)

1
/*
2
 *  i386 helpers (without register variable usage)
3
 *
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
#include <stdarg.h>
21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <string.h>
24
#include <inttypes.h>
25
#include <signal.h>
26
#include <assert.h>
27

    
28
#include "cpu.h"
29
#include "exec-all.h"
30
#include "svm.h"
31
#include "qemu-common.h"
32

    
33
//#define DEBUG_MMU
34

    
35
static int cpu_x86_register (CPUX86State *env, const char *cpu_model);
36

    
37
static void add_flagname_to_bitmaps(char *flagname, uint32_t *features, 
38
                                    uint32_t *ext_features, 
39
                                    uint32_t *ext2_features, 
40
                                    uint32_t *ext3_features)
41
{
42
    int i;
43
    /* feature flags taken from "Intel Processor Identification and the CPUID
44
     * Instruction" and AMD's "CPUID Specification". In cases of disagreement 
45
     * about feature names, the Linux name is used. */
46
    const char *feature_name[] = {
47
        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
48
        "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
49
        "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, NULL, "ds" /* Intel dts */, "acpi", "mmx",
50
        "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
51
    };
52
    const char *ext_feature_name[] = {
53
       "pni" /* Intel,AMD sse3 */, NULL, NULL, "monitor", "ds_cpl", "vmx", NULL /* Linux smx */, "est",
54
       "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
55
       NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
56
       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
57
    };
58
    const char *ext2_feature_name[] = {
59
       "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
60
       "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", "mttr", "pge", "mca", "cmov",
61
       "pat", "pse36", NULL, NULL /* Linux mp */, "nx" /* Intel xd */, NULL, "mmxext", "mmx",
62
       "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
63
    };
64
    const char *ext3_feature_name[] = {
65
       "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
66
       "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
67
       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
68
       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
69
    };
70

    
71
    for ( i = 0 ; i < 32 ; i++ ) 
72
        if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
73
            *features |= 1 << i;
74
            return;
75
        }
76
    for ( i = 0 ; i < 32 ; i++ ) 
77
        if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) {
78
            *ext_features |= 1 << i;
79
            return;
80
        }
81
    for ( i = 0 ; i < 32 ; i++ ) 
82
        if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) {
83
            *ext2_features |= 1 << i;
84
            return;
85
        }
86
    for ( i = 0 ; i < 32 ; i++ ) 
87
        if (ext3_feature_name[i] && !strcmp (flagname, ext3_feature_name[i])) {
88
            *ext3_features |= 1 << i;
89
            return;
90
        }
91
    fprintf(stderr, "CPU feature %s not found\n", flagname);
92
}
93

    
94
CPUX86State *cpu_x86_init(const char *cpu_model)
95
{
96
    CPUX86State *env;
97
    static int inited;
98

    
99
    env = qemu_mallocz(sizeof(CPUX86State));
100
    if (!env)
101
        return NULL;
102
    cpu_exec_init(env);
103
    env->cpu_model_str = cpu_model;
104

    
105
    /* init various static tables */
106
    if (!inited) {
107
        inited = 1;
108
        optimize_flags_init();
109
    }
110
    if (cpu_x86_register(env, cpu_model) < 0) {
111
        cpu_x86_close(env);
112
        return NULL;
113
    }
114
    cpu_reset(env);
115
#ifdef USE_KQEMU
116
    kqemu_init(env);
117
#endif
118
    return env;
119
}
120

    
121
typedef struct x86_def_t {
122
    const char *name;
123
    uint32_t level;
124
    uint32_t vendor1, vendor2, vendor3;
125
    int family;
126
    int model;
127
    int stepping;
128
    uint32_t features, ext_features, ext2_features, ext3_features;
129
    uint32_t xlevel;
130
} x86_def_t;
131

    
132
#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
133
#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
134
          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX)
135
#define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
136
          CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
137
          CPUID_PSE36 | CPUID_FXSR)
138
#define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE)
139
#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
140
          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
141
          CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
142
          CPUID_PAE | CPUID_SEP | CPUID_APIC)
143
static x86_def_t x86_defs[] = {
144
#ifdef TARGET_X86_64
145
    {
146
        .name = "qemu64",
147
        .level = 2,
148
        .vendor1 = 0x68747541, /* "Auth" */
149
        .vendor2 = 0x69746e65, /* "enti" */
150
        .vendor3 = 0x444d4163, /* "cAMD" */
151
        .family = 6,
152
        .model = 2,
153
        .stepping = 3,
154
        .features = PPRO_FEATURES | 
155
        /* these features are needed for Win64 and aren't fully implemented */
156
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
157
        /* this feature is needed for Solaris and isn't fully implemented */
158
            CPUID_PSE36,
159
        .ext_features = CPUID_EXT_SSE3,
160
        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 
161
            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
162
            CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
163
        .ext3_features = CPUID_EXT3_SVM,
164
        .xlevel = 0x8000000A,
165
    },
166
#endif
167
    {
168
        .name = "qemu32",
169
        .level = 2,
170
        .family = 6,
171
        .model = 3,
172
        .stepping = 3,
173
        .features = PPRO_FEATURES,
174
        .ext_features = CPUID_EXT_SSE3,
175
        .xlevel = 0,
176
    },
177
    {
178
        .name = "486",
179
        .level = 0,
180
        .family = 4,
181
        .model = 0,
182
        .stepping = 0,
183
        .features = I486_FEATURES,
184
        .xlevel = 0,
185
    },
186
    {
187
        .name = "pentium",
188
        .level = 1,
189
        .family = 5,
190
        .model = 4,
191
        .stepping = 3,
192
        .features = PENTIUM_FEATURES,
193
        .xlevel = 0,
194
    },
195
    {
196
        .name = "pentium2",
197
        .level = 2,
198
        .family = 6,
199
        .model = 5,
200
        .stepping = 2,
201
        .features = PENTIUM2_FEATURES,
202
        .xlevel = 0,
203
    },
204
    {
205
        .name = "pentium3",
206
        .level = 2,
207
        .family = 6,
208
        .model = 7,
209
        .stepping = 3,
210
        .features = PENTIUM3_FEATURES,
211
        .xlevel = 0,
212
    },
213
    {
214
        .name = "athlon",
215
        .level = 2,
216
        .vendor1 = 0x68747541, /* "Auth" */
217
        .vendor2 = 0x69746e65, /* "enti" */
218
        .vendor3 = 0x444d4163, /* "cAMD" */
219
        .family = 6,
220
        .model = 2,
221
        .stepping = 3,
222
        .features = PPRO_FEATURES | PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA,
223
        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
224
        .xlevel = 0x80000008,
225
    },
226
};
227

    
228
static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
229
{
230
    unsigned int i;
231
    x86_def_t *def;
232

    
233
    char *s = strdup(cpu_model);
234
    char *featurestr, *name = strtok(s, ",");
235
    uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0;
236
    uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0;
237
    int family = -1, model = -1, stepping = -1;
238

    
239
    def = NULL;
240
    for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++) {
241
        if (strcmp(name, x86_defs[i].name) == 0) {
242
            def = &x86_defs[i];
243
            break;
244
        }
245
    }
246
    if (!def)
247
        goto error;
248
    memcpy(x86_cpu_def, def, sizeof(*def));
249

    
250
    featurestr = strtok(NULL, ",");
251

    
252
    while (featurestr) {
253
        char *val;
254
        if (featurestr[0] == '+') {
255
            add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features);
256
        } else if (featurestr[0] == '-') {
257
            add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features);
258
        } else if ((val = strchr(featurestr, '='))) {
259
            *val = 0; val++;
260
            if (!strcmp(featurestr, "family")) {
261
                char *err;
262
                family = strtol(val, &err, 10);
263
                if (!*val || *err || family < 0) {
264
                    fprintf(stderr, "bad numerical value %s\n", val);
265
                    x86_cpu_def = 0;
266
                    goto error;
267
                }
268
                x86_cpu_def->family = family;
269
            } else if (!strcmp(featurestr, "model")) {
270
                char *err;
271
                model = strtol(val, &err, 10);
272
                if (!*val || *err || model < 0 || model > 0xf) {
273
                    fprintf(stderr, "bad numerical value %s\n", val);
274
                    x86_cpu_def = 0;
275
                    goto error;
276
                }
277
                x86_cpu_def->model = model;
278
            } else if (!strcmp(featurestr, "stepping")) {
279
                char *err;
280
                stepping = strtol(val, &err, 10);
281
                if (!*val || *err || stepping < 0 || stepping > 0xf) {
282
                    fprintf(stderr, "bad numerical value %s\n", val);
283
                    x86_cpu_def = 0;
284
                    goto error;
285
                }
286
                x86_cpu_def->stepping = stepping;
287
            } else {
288
                fprintf(stderr, "unrecognized feature %s\n", featurestr);
289
                x86_cpu_def = 0;
290
                goto error;
291
            }
292
        } else {
293
            fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
294
            x86_cpu_def = 0;
295
            goto error;
296
        }
297
        featurestr = strtok(NULL, ",");
298
    }
299
    x86_cpu_def->features |= plus_features;
300
    x86_cpu_def->ext_features |= plus_ext_features;
301
    x86_cpu_def->ext2_features |= plus_ext2_features;
302
    x86_cpu_def->ext3_features |= plus_ext3_features;
303
    x86_cpu_def->features &= ~minus_features;
304
    x86_cpu_def->ext_features &= ~minus_ext_features;
305
    x86_cpu_def->ext2_features &= ~minus_ext2_features;
306
    x86_cpu_def->ext3_features &= ~minus_ext3_features;
307
    free(s);
308
    return 0;
309

    
310
error:
311
    free(s);
312
    return -1;
313
}
314

    
315
void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
316
{
317
    unsigned int i;
318

    
319
    for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++)
320
        (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
321
}
322

    
323
static int cpu_x86_register (CPUX86State *env, const char *cpu_model)
324
{
325
    x86_def_t def1, *def = &def1;
326

    
327
    if (cpu_x86_find_by_name(def, cpu_model) < 0)
328
        return -1;
329
    if (def->vendor1) {
330
        env->cpuid_vendor1 = def->vendor1;
331
        env->cpuid_vendor2 = def->vendor2;
332
        env->cpuid_vendor3 = def->vendor3;
333
    } else {
334
        env->cpuid_vendor1 = 0x756e6547; /* "Genu" */
335
        env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
336
        env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
337
    }
338
    env->cpuid_level = def->level;
339
    env->cpuid_version = (def->family << 8) | (def->model << 4) | def->stepping;
340
    env->cpuid_features = def->features;
341
    env->pat = 0x0007040600070406ULL;
342
    env->cpuid_ext_features = def->ext_features;
343
    env->cpuid_ext2_features = def->ext2_features;
344
    env->cpuid_xlevel = def->xlevel;
345
    env->cpuid_ext3_features = def->ext3_features;
346
    {
347
        const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
348
        int c, len, i;
349
        len = strlen(model_id);
350
        for(i = 0; i < 48; i++) {
351
            if (i >= len)
352
                c = '\0';
353
            else
354
                c = model_id[i];
355
            env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
356
        }
357
    }
358
    return 0;
359
}
360

    
361
/* NOTE: must be called outside the CPU execute loop */
362
void cpu_reset(CPUX86State *env)
363
{
364
    int i;
365

    
366
    memset(env, 0, offsetof(CPUX86State, breakpoints));
367

    
368
    tlb_flush(env, 1);
369

    
370
    env->old_exception = -1;
371

    
372
    /* init to reset state */
373

    
374
#ifdef CONFIG_SOFTMMU
375
    env->hflags |= HF_SOFTMMU_MASK;
376
#endif
377
    env->hflags |= HF_GIF_MASK;
378

    
379
    cpu_x86_update_cr0(env, 0x60000010);
380
    env->a20_mask = ~0x0;
381
    env->smbase = 0x30000;
382

    
383
    env->idt.limit = 0xffff;
384
    env->gdt.limit = 0xffff;
385
    env->ldt.limit = 0xffff;
386
    env->ldt.flags = DESC_P_MASK;
387
    env->tr.limit = 0xffff;
388
    env->tr.flags = DESC_P_MASK;
389

    
390
    cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, 0);
391
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, 0);
392
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, 0);
393
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, 0);
394
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, 0);
395
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0);
396

    
397
    env->eip = 0xfff0;
398
    env->regs[R_EDX] = env->cpuid_version;
399

    
400
    env->eflags = 0x2;
401

    
402
    /* FPU init */
403
    for(i = 0;i < 8; i++)
404
        env->fptags[i] = 1;
405
    env->fpuc = 0x37f;
406

    
407
    env->mxcsr = 0x1f80;
408
}
409

    
410
void cpu_x86_close(CPUX86State *env)
411
{
412
    free(env);
413
}
414

    
415
/***********************************************************/
416
/* x86 debug */
417

    
418
static const char *cc_op_str[] = {
419
    "DYNAMIC",
420
    "EFLAGS",
421

    
422
    "MULB",
423
    "MULW",
424
    "MULL",
425
    "MULQ",
426

    
427
    "ADDB",
428
    "ADDW",
429
    "ADDL",
430
    "ADDQ",
431

    
432
    "ADCB",
433
    "ADCW",
434
    "ADCL",
435
    "ADCQ",
436

    
437
    "SUBB",
438
    "SUBW",
439
    "SUBL",
440
    "SUBQ",
441

    
442
    "SBBB",
443
    "SBBW",
444
    "SBBL",
445
    "SBBQ",
446

    
447
    "LOGICB",
448
    "LOGICW",
449
    "LOGICL",
450
    "LOGICQ",
451

    
452
    "INCB",
453
    "INCW",
454
    "INCL",
455
    "INCQ",
456

    
457
    "DECB",
458
    "DECW",
459
    "DECL",
460
    "DECQ",
461

    
462
    "SHLB",
463
    "SHLW",
464
    "SHLL",
465
    "SHLQ",
466

    
467
    "SARB",
468
    "SARW",
469
    "SARL",
470
    "SARQ",
471
};
472

    
473
void cpu_dump_state(CPUState *env, FILE *f,
474
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
475
                    int flags)
476
{
477
    int eflags, i, nb;
478
    char cc_op_name[32];
479
    static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
480

    
481
    eflags = env->eflags;
482
#ifdef TARGET_X86_64
483
    if (env->hflags & HF_CS64_MASK) {
484
        cpu_fprintf(f,
485
                    "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
486
                    "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
487
                    "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
488
                    "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
489
                    "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
490
                    env->regs[R_EAX],
491
                    env->regs[R_EBX],
492
                    env->regs[R_ECX],
493
                    env->regs[R_EDX],
494
                    env->regs[R_ESI],
495
                    env->regs[R_EDI],
496
                    env->regs[R_EBP],
497
                    env->regs[R_ESP],
498
                    env->regs[8],
499
                    env->regs[9],
500
                    env->regs[10],
501
                    env->regs[11],
502
                    env->regs[12],
503
                    env->regs[13],
504
                    env->regs[14],
505
                    env->regs[15],
506
                    env->eip, eflags,
507
                    eflags & DF_MASK ? 'D' : '-',
508
                    eflags & CC_O ? 'O' : '-',
509
                    eflags & CC_S ? 'S' : '-',
510
                    eflags & CC_Z ? 'Z' : '-',
511
                    eflags & CC_A ? 'A' : '-',
512
                    eflags & CC_P ? 'P' : '-',
513
                    eflags & CC_C ? 'C' : '-',
514
                    env->hflags & HF_CPL_MASK,
515
                    (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
516
                    (int)(env->a20_mask >> 20) & 1,
517
                    (env->hflags >> HF_SMM_SHIFT) & 1,
518
                    env->halted);
519
    } else
520
#endif
521
    {
522
        cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
523
                    "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
524
                    "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
525
                    (uint32_t)env->regs[R_EAX],
526
                    (uint32_t)env->regs[R_EBX],
527
                    (uint32_t)env->regs[R_ECX],
528
                    (uint32_t)env->regs[R_EDX],
529
                    (uint32_t)env->regs[R_ESI],
530
                    (uint32_t)env->regs[R_EDI],
531
                    (uint32_t)env->regs[R_EBP],
532
                    (uint32_t)env->regs[R_ESP],
533
                    (uint32_t)env->eip, eflags,
534
                    eflags & DF_MASK ? 'D' : '-',
535
                    eflags & CC_O ? 'O' : '-',
536
                    eflags & CC_S ? 'S' : '-',
537
                    eflags & CC_Z ? 'Z' : '-',
538
                    eflags & CC_A ? 'A' : '-',
539
                    eflags & CC_P ? 'P' : '-',
540
                    eflags & CC_C ? 'C' : '-',
541
                    env->hflags & HF_CPL_MASK,
542
                    (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
543
                    (int)(env->a20_mask >> 20) & 1,
544
                    (env->hflags >> HF_SMM_SHIFT) & 1,
545
                    env->halted);
546
    }
547

    
548
#ifdef TARGET_X86_64
549
    if (env->hflags & HF_LMA_MASK) {
550
        for(i = 0; i < 6; i++) {
551
            SegmentCache *sc = &env->segs[i];
552
            cpu_fprintf(f, "%s =%04x %016" PRIx64 " %08x %08x\n",
553
                        seg_name[i],
554
                        sc->selector,
555
                        sc->base,
556
                        sc->limit,
557
                        sc->flags);
558
        }
559
        cpu_fprintf(f, "LDT=%04x %016" PRIx64 " %08x %08x\n",
560
                    env->ldt.selector,
561
                    env->ldt.base,
562
                    env->ldt.limit,
563
                    env->ldt.flags);
564
        cpu_fprintf(f, "TR =%04x %016" PRIx64 " %08x %08x\n",
565
                    env->tr.selector,
566
                    env->tr.base,
567
                    env->tr.limit,
568
                    env->tr.flags);
569
        cpu_fprintf(f, "GDT=     %016" PRIx64 " %08x\n",
570
                    env->gdt.base, env->gdt.limit);
571
        cpu_fprintf(f, "IDT=     %016" PRIx64 " %08x\n",
572
                    env->idt.base, env->idt.limit);
573
        cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
574
                    (uint32_t)env->cr[0],
575
                    env->cr[2],
576
                    env->cr[3],
577
                    (uint32_t)env->cr[4]);
578
    } else
579
#endif
580
    {
581
        for(i = 0; i < 6; i++) {
582
            SegmentCache *sc = &env->segs[i];
583
            cpu_fprintf(f, "%s =%04x %08x %08x %08x\n",
584
                        seg_name[i],
585
                        sc->selector,
586
                        (uint32_t)sc->base,
587
                        sc->limit,
588
                        sc->flags);
589
        }
590
        cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n",
591
                    env->ldt.selector,
592
                    (uint32_t)env->ldt.base,
593
                    env->ldt.limit,
594
                    env->ldt.flags);
595
        cpu_fprintf(f, "TR =%04x %08x %08x %08x\n",
596
                    env->tr.selector,
597
                    (uint32_t)env->tr.base,
598
                    env->tr.limit,
599
                    env->tr.flags);
600
        cpu_fprintf(f, "GDT=     %08x %08x\n",
601
                    (uint32_t)env->gdt.base, env->gdt.limit);
602
        cpu_fprintf(f, "IDT=     %08x %08x\n",
603
                    (uint32_t)env->idt.base, env->idt.limit);
604
        cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
605
                    (uint32_t)env->cr[0],
606
                    (uint32_t)env->cr[2],
607
                    (uint32_t)env->cr[3],
608
                    (uint32_t)env->cr[4]);
609
    }
610
    if (flags & X86_DUMP_CCOP) {
611
        if ((unsigned)env->cc_op < CC_OP_NB)
612
            snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
613
        else
614
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
615
#ifdef TARGET_X86_64
616
        if (env->hflags & HF_CS64_MASK) {
617
            cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
618
                        env->cc_src, env->cc_dst,
619
                        cc_op_name);
620
        } else
621
#endif
622
        {
623
            cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
624
                        (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
625
                        cc_op_name);
626
        }
627
    }
628
    if (flags & X86_DUMP_FPU) {
629
        int fptag;
630
        fptag = 0;
631
        for(i = 0; i < 8; i++) {
632
            fptag |= ((!env->fptags[i]) << i);
633
        }
634
        cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
635
                    env->fpuc,
636
                    (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
637
                    env->fpstt,
638
                    fptag,
639
                    env->mxcsr);
640
        for(i=0;i<8;i++) {
641
#if defined(USE_X86LDOUBLE)
642
            union {
643
                long double d;
644
                struct {
645
                    uint64_t lower;
646
                    uint16_t upper;
647
                } l;
648
            } tmp;
649
            tmp.d = env->fpregs[i].d;
650
            cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
651
                        i, tmp.l.lower, tmp.l.upper);
652
#else
653
            cpu_fprintf(f, "FPR%d=%016" PRIx64,
654
                        i, env->fpregs[i].mmx.q);
655
#endif
656
            if ((i & 1) == 1)
657
                cpu_fprintf(f, "\n");
658
            else
659
                cpu_fprintf(f, " ");
660
        }
661
        if (env->hflags & HF_CS64_MASK)
662
            nb = 16;
663
        else
664
            nb = 8;
665
        for(i=0;i<nb;i++) {
666
            cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
667
                        i,
668
                        env->xmm_regs[i].XMM_L(3),
669
                        env->xmm_regs[i].XMM_L(2),
670
                        env->xmm_regs[i].XMM_L(1),
671
                        env->xmm_regs[i].XMM_L(0));
672
            if ((i & 1) == 1)
673
                cpu_fprintf(f, "\n");
674
            else
675
                cpu_fprintf(f, " ");
676
        }
677
    }
678
}
679

    
680
/***********************************************************/
681
/* x86 mmu */
682
/* XXX: add PGE support */
683

    
684
void cpu_x86_set_a20(CPUX86State *env, int a20_state)
685
{
686
    a20_state = (a20_state != 0);
687
    if (a20_state != ((env->a20_mask >> 20) & 1)) {
688
#if defined(DEBUG_MMU)
689
        printf("A20 update: a20=%d\n", a20_state);
690
#endif
691
        /* if the cpu is currently executing code, we must unlink it and
692
           all the potentially executing TB */
693
        cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
694

    
695
        /* when a20 is changed, all the MMU mappings are invalid, so
696
           we must flush everything */
697
        tlb_flush(env, 1);
698
        env->a20_mask = (~0x100000) | (a20_state << 20);
699
    }
700
}
701

    
702
void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
703
{
704
    int pe_state;
705

    
706
#if defined(DEBUG_MMU)
707
    printf("CR0 update: CR0=0x%08x\n", new_cr0);
708
#endif
709
    if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
710
        (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
711
        tlb_flush(env, 1);
712
    }
713

    
714
#ifdef TARGET_X86_64
715
    if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
716
        (env->efer & MSR_EFER_LME)) {
717
        /* enter in long mode */
718
        /* XXX: generate an exception */
719
        if (!(env->cr[4] & CR4_PAE_MASK))
720
            return;
721
        env->efer |= MSR_EFER_LMA;
722
        env->hflags |= HF_LMA_MASK;
723
    } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
724
               (env->efer & MSR_EFER_LMA)) {
725
        /* exit long mode */
726
        env->efer &= ~MSR_EFER_LMA;
727
        env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
728
        env->eip &= 0xffffffff;
729
    }
730
#endif
731
    env->cr[0] = new_cr0 | CR0_ET_MASK;
732

    
733
    /* update PE flag in hidden flags */
734
    pe_state = (env->cr[0] & CR0_PE_MASK);
735
    env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
736
    /* ensure that ADDSEG is always set in real mode */
737
    env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
738
    /* update FPU flags */
739
    env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
740
        ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
741
}
742

    
743
/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
744
   the PDPT */
745
void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
746
{
747
    env->cr[3] = new_cr3;
748
    if (env->cr[0] & CR0_PG_MASK) {
749
#if defined(DEBUG_MMU)
750
        printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
751
#endif
752
        tlb_flush(env, 0);
753
    }
754
}
755

    
756
void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
757
{
758
#if defined(DEBUG_MMU)
759
    printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
760
#endif
761
    if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
762
        (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
763
        tlb_flush(env, 1);
764
    }
765
    /* SSE handling */
766
    if (!(env->cpuid_features & CPUID_SSE))
767
        new_cr4 &= ~CR4_OSFXSR_MASK;
768
    if (new_cr4 & CR4_OSFXSR_MASK)
769
        env->hflags |= HF_OSFXSR_MASK;
770
    else
771
        env->hflags &= ~HF_OSFXSR_MASK;
772

    
773
    env->cr[4] = new_cr4;
774
}
775

    
776
/* XXX: also flush 4MB pages */
777
void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr)
778
{
779
    tlb_flush_page(env, addr);
780
}
781

    
782
#if defined(CONFIG_USER_ONLY)
783

    
784
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
785
                             int is_write, int mmu_idx, int is_softmmu)
786
{
787
    /* user mode only emulation */
788
    is_write &= 1;
789
    env->cr[2] = addr;
790
    env->error_code = (is_write << PG_ERROR_W_BIT);
791
    env->error_code |= PG_ERROR_U_MASK;
792
    env->exception_index = EXCP0E_PAGE;
793
    return 1;
794
}
795

    
796
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
797
{
798
    return addr;
799
}
800

    
801
#else
802

    
803
/* XXX: This value should match the one returned by CPUID
804
 * and in exec.c */
805
#if defined(USE_KQEMU)
806
#define PHYS_ADDR_MASK 0xfffff000L
807
#else
808
# if defined(TARGET_X86_64)
809
# define PHYS_ADDR_MASK 0xfffffff000L
810
# else
811
# define PHYS_ADDR_MASK 0xffffff000L
812
# endif
813
#endif
814

    
815
/* return value:
816
   -1 = cannot handle fault
817
   0  = nothing more to do
818
   1  = generate PF fault
819
   2  = soft MMU activation required for this block
820
*/
821
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
822
                             int is_write1, int mmu_idx, int is_softmmu)
823
{
824
    uint64_t ptep, pte;
825
    target_ulong pde_addr, pte_addr;
826
    int error_code, is_dirty, prot, page_size, ret, is_write, is_user;
827
    target_phys_addr_t paddr;
828
    uint32_t page_offset;
829
    target_ulong vaddr, virt_addr;
830

    
831
    is_user = mmu_idx == MMU_USER_IDX;
832
#if defined(DEBUG_MMU)
833
    printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
834
           addr, is_write1, is_user, env->eip);
835
#endif
836
    is_write = is_write1 & 1;
837

    
838
    if (!(env->cr[0] & CR0_PG_MASK)) {
839
        pte = addr;
840
        virt_addr = addr & TARGET_PAGE_MASK;
841
        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
842
        page_size = 4096;
843
        goto do_mapping;
844
    }
845

    
846
    if (env->cr[4] & CR4_PAE_MASK) {
847
        uint64_t pde, pdpe;
848
        target_ulong pdpe_addr;
849

    
850
#ifdef TARGET_X86_64
851
        if (env->hflags & HF_LMA_MASK) {
852
            uint64_t pml4e_addr, pml4e;
853
            int32_t sext;
854

    
855
            /* test virtual address sign extension */
856
            sext = (int64_t)addr >> 47;
857
            if (sext != 0 && sext != -1) {
858
                env->error_code = 0;
859
                env->exception_index = EXCP0D_GPF;
860
                return 1;
861
            }
862

    
863
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
864
                env->a20_mask;
865
            pml4e = ldq_phys(pml4e_addr);
866
            if (!(pml4e & PG_PRESENT_MASK)) {
867
                error_code = 0;
868
                goto do_fault;
869
            }
870
            if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
871
                error_code = PG_ERROR_RSVD_MASK;
872
                goto do_fault;
873
            }
874
            if (!(pml4e & PG_ACCESSED_MASK)) {
875
                pml4e |= PG_ACCESSED_MASK;
876
                stl_phys_notdirty(pml4e_addr, pml4e);
877
            }
878
            ptep = pml4e ^ PG_NX_MASK;
879
            pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
880
                env->a20_mask;
881
            pdpe = ldq_phys(pdpe_addr);
882
            if (!(pdpe & PG_PRESENT_MASK)) {
883
                error_code = 0;
884
                goto do_fault;
885
            }
886
            if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
887
                error_code = PG_ERROR_RSVD_MASK;
888
                goto do_fault;
889
            }
890
            ptep &= pdpe ^ PG_NX_MASK;
891
            if (!(pdpe & PG_ACCESSED_MASK)) {
892
                pdpe |= PG_ACCESSED_MASK;
893
                stl_phys_notdirty(pdpe_addr, pdpe);
894
            }
895
        } else
896
#endif
897
        {
898
            /* XXX: load them when cr3 is loaded ? */
899
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
900
                env->a20_mask;
901
            pdpe = ldq_phys(pdpe_addr);
902
            if (!(pdpe & PG_PRESENT_MASK)) {
903
                error_code = 0;
904
                goto do_fault;
905
            }
906
            ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
907
        }
908

    
909
        pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
910
            env->a20_mask;
911
        pde = ldq_phys(pde_addr);
912
        if (!(pde & PG_PRESENT_MASK)) {
913
            error_code = 0;
914
            goto do_fault;
915
        }
916
        if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
917
            error_code = PG_ERROR_RSVD_MASK;
918
            goto do_fault;
919
        }
920
        ptep &= pde ^ PG_NX_MASK;
921
        if (pde & PG_PSE_MASK) {
922
            /* 2 MB page */
923
            page_size = 2048 * 1024;
924
            ptep ^= PG_NX_MASK;
925
            if ((ptep & PG_NX_MASK) && is_write1 == 2)
926
                goto do_fault_protect;
927
            if (is_user) {
928
                if (!(ptep & PG_USER_MASK))
929
                    goto do_fault_protect;
930
                if (is_write && !(ptep & PG_RW_MASK))
931
                    goto do_fault_protect;
932
            } else {
933
                if ((env->cr[0] & CR0_WP_MASK) &&
934
                    is_write && !(ptep & PG_RW_MASK))
935
                    goto do_fault_protect;
936
            }
937
            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
938
            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
939
                pde |= PG_ACCESSED_MASK;
940
                if (is_dirty)
941
                    pde |= PG_DIRTY_MASK;
942
                stl_phys_notdirty(pde_addr, pde);
943
            }
944
            /* align to page_size */
945
            pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
946
            virt_addr = addr & ~(page_size - 1);
947
        } else {
948
            /* 4 KB page */
949
            if (!(pde & PG_ACCESSED_MASK)) {
950
                pde |= PG_ACCESSED_MASK;
951
                stl_phys_notdirty(pde_addr, pde);
952
            }
953
            pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
954
                env->a20_mask;
955
            pte = ldq_phys(pte_addr);
956
            if (!(pte & PG_PRESENT_MASK)) {
957
                error_code = 0;
958
                goto do_fault;
959
            }
960
            if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
961
                error_code = PG_ERROR_RSVD_MASK;
962
                goto do_fault;
963
            }
964
            /* combine pde and pte nx, user and rw protections */
965
            ptep &= pte ^ PG_NX_MASK;
966
            ptep ^= PG_NX_MASK;
967
            if ((ptep & PG_NX_MASK) && is_write1 == 2)
968
                goto do_fault_protect;
969
            if (is_user) {
970
                if (!(ptep & PG_USER_MASK))
971
                    goto do_fault_protect;
972
                if (is_write && !(ptep & PG_RW_MASK))
973
                    goto do_fault_protect;
974
            } else {
975
                if ((env->cr[0] & CR0_WP_MASK) &&
976
                    is_write && !(ptep & PG_RW_MASK))
977
                    goto do_fault_protect;
978
            }
979
            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
980
            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
981
                pte |= PG_ACCESSED_MASK;
982
                if (is_dirty)
983
                    pte |= PG_DIRTY_MASK;
984
                stl_phys_notdirty(pte_addr, pte);
985
            }
986
            page_size = 4096;
987
            virt_addr = addr & ~0xfff;
988
            pte = pte & (PHYS_ADDR_MASK | 0xfff);
989
        }
990
    } else {
991
        uint32_t pde;
992

    
993
        /* page directory entry */
994
        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
995
            env->a20_mask;
996
        pde = ldl_phys(pde_addr);
997
        if (!(pde & PG_PRESENT_MASK)) {
998
            error_code = 0;
999
            goto do_fault;
1000
        }
1001
        /* if PSE bit is set, then we use a 4MB page */
1002
        if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
1003
            page_size = 4096 * 1024;
1004
            if (is_user) {
1005
                if (!(pde & PG_USER_MASK))
1006
                    goto do_fault_protect;
1007
                if (is_write && !(pde & PG_RW_MASK))
1008
                    goto do_fault_protect;
1009
            } else {
1010
                if ((env->cr[0] & CR0_WP_MASK) &&
1011
                    is_write && !(pde & PG_RW_MASK))
1012
                    goto do_fault_protect;
1013
            }
1014
            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
1015
            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
1016
                pde |= PG_ACCESSED_MASK;
1017
                if (is_dirty)
1018
                    pde |= PG_DIRTY_MASK;
1019
                stl_phys_notdirty(pde_addr, pde);
1020
            }
1021

    
1022
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
1023
            ptep = pte;
1024
            virt_addr = addr & ~(page_size - 1);
1025
        } else {
1026
            if (!(pde & PG_ACCESSED_MASK)) {
1027
                pde |= PG_ACCESSED_MASK;
1028
                stl_phys_notdirty(pde_addr, pde);
1029
            }
1030

    
1031
            /* page directory entry */
1032
            pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
1033
                env->a20_mask;
1034
            pte = ldl_phys(pte_addr);
1035
            if (!(pte & PG_PRESENT_MASK)) {
1036
                error_code = 0;
1037
                goto do_fault;
1038
            }
1039
            /* combine pde and pte user and rw protections */
1040
            ptep = pte & pde;
1041
            if (is_user) {
1042
                if (!(ptep & PG_USER_MASK))
1043
                    goto do_fault_protect;
1044
                if (is_write && !(ptep & PG_RW_MASK))
1045
                    goto do_fault_protect;
1046
            } else {
1047
                if ((env->cr[0] & CR0_WP_MASK) &&
1048
                    is_write && !(ptep & PG_RW_MASK))
1049
                    goto do_fault_protect;
1050
            }
1051
            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
1052
            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
1053
                pte |= PG_ACCESSED_MASK;
1054
                if (is_dirty)
1055
                    pte |= PG_DIRTY_MASK;
1056
                stl_phys_notdirty(pte_addr, pte);
1057
            }
1058
            page_size = 4096;
1059
            virt_addr = addr & ~0xfff;
1060
        }
1061
    }
1062
    /* the page can be put in the TLB */
1063
    prot = PAGE_READ;
1064
    if (!(ptep & PG_NX_MASK))
1065
        prot |= PAGE_EXEC;
1066
    if (pte & PG_DIRTY_MASK) {
1067
        /* only set write access if already dirty... otherwise wait
1068
           for dirty access */
1069
        if (is_user) {
1070
            if (ptep & PG_RW_MASK)
1071
                prot |= PAGE_WRITE;
1072
        } else {
1073
            if (!(env->cr[0] & CR0_WP_MASK) ||
1074
                (ptep & PG_RW_MASK))
1075
                prot |= PAGE_WRITE;
1076
        }
1077
    }
1078
 do_mapping:
1079
    pte = pte & env->a20_mask;
1080

    
1081
    /* Even if 4MB pages, we map only one 4KB page in the cache to
1082
       avoid filling it too fast */
1083
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
1084
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
1085
    vaddr = virt_addr + page_offset;
1086

    
1087
    ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
1088
    return ret;
1089
 do_fault_protect:
1090
    error_code = PG_ERROR_P_MASK;
1091
 do_fault:
1092
    error_code |= (is_write << PG_ERROR_W_BIT);
1093
    if (is_user)
1094
        error_code |= PG_ERROR_U_MASK;
1095
    if (is_write1 == 2 &&
1096
        (env->efer & MSR_EFER_NXE) &&
1097
        (env->cr[4] & CR4_PAE_MASK))
1098
        error_code |= PG_ERROR_I_D_MASK;
1099
    if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) {
1100
        /* cr2 is not modified in case of exceptions */
1101
        stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 
1102
                 addr);
1103
    } else {
1104
        env->cr[2] = addr;
1105
    }
1106
    env->error_code = error_code;
1107
    env->exception_index = EXCP0E_PAGE;
1108
    return 1;
1109
}
1110

    
1111
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1112
{
1113
    target_ulong pde_addr, pte_addr;
1114
    uint64_t pte;
1115
    target_phys_addr_t paddr;
1116
    uint32_t page_offset;
1117
    int page_size;
1118

    
1119
    if (env->cr[4] & CR4_PAE_MASK) {
1120
        target_ulong pdpe_addr;
1121
        uint64_t pde, pdpe;
1122

    
1123
#ifdef TARGET_X86_64
1124
        if (env->hflags & HF_LMA_MASK) {
1125
            uint64_t pml4e_addr, pml4e;
1126
            int32_t sext;
1127

    
1128
            /* test virtual address sign extension */
1129
            sext = (int64_t)addr >> 47;
1130
            if (sext != 0 && sext != -1)
1131
                return -1;
1132

    
1133
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
1134
                env->a20_mask;
1135
            pml4e = ldq_phys(pml4e_addr);
1136
            if (!(pml4e & PG_PRESENT_MASK))
1137
                return -1;
1138

    
1139
            pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
1140
                env->a20_mask;
1141
            pdpe = ldq_phys(pdpe_addr);
1142
            if (!(pdpe & PG_PRESENT_MASK))
1143
                return -1;
1144
        } else
1145
#endif
1146
        {
1147
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
1148
                env->a20_mask;
1149
            pdpe = ldq_phys(pdpe_addr);
1150
            if (!(pdpe & PG_PRESENT_MASK))
1151
                return -1;
1152
        }
1153

    
1154
        pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
1155
            env->a20_mask;
1156
        pde = ldq_phys(pde_addr);
1157
        if (!(pde & PG_PRESENT_MASK)) {
1158
            return -1;
1159
        }
1160
        if (pde & PG_PSE_MASK) {
1161
            /* 2 MB page */
1162
            page_size = 2048 * 1024;
1163
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
1164
        } else {
1165
            /* 4 KB page */
1166
            pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
1167
                env->a20_mask;
1168
            page_size = 4096;
1169
            pte = ldq_phys(pte_addr);
1170
        }
1171
    } else {
1172
        uint32_t pde;
1173

    
1174
        if (!(env->cr[0] & CR0_PG_MASK)) {
1175
            pte = addr;
1176
            page_size = 4096;
1177
        } else {
1178
            /* page directory entry */
1179
            pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
1180
            pde = ldl_phys(pde_addr);
1181
            if (!(pde & PG_PRESENT_MASK))
1182
                return -1;
1183
            if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
1184
                pte = pde & ~0x003ff000; /* align to 4MB */
1185
                page_size = 4096 * 1024;
1186
            } else {
1187
                /* page directory entry */
1188
                pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
1189
                pte = ldl_phys(pte_addr);
1190
                if (!(pte & PG_PRESENT_MASK))
1191
                    return -1;
1192
                page_size = 4096;
1193
            }
1194
        }
1195
        pte = pte & env->a20_mask;
1196
    }
1197

    
1198
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
1199
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
1200
    return paddr;
1201
}
1202
#endif /* !CONFIG_USER_ONLY */