Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ 3e98dc8e

History | View | Annotate | Download (38 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

    
32
//#define DEBUG_MMU
33

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

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

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

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

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

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

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

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

    
206
static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
207
{
208
    unsigned int i;
209
    x86_def_t *def;
210

    
211
    char *s = strdup(cpu_model);
212
    char *featurestr, *name = strtok(s, ",");
213
    uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0;
214
    uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0;
215
    int family = -1, model = -1, stepping = -1;
216

    
217
    def = NULL;
218
    for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++) {
219
        if (strcmp(name, x86_defs[i].name) == 0) {
220
            def = &x86_defs[i];
221
            break;
222
        }
223
    }
224
    if (!def)
225
        goto error;
226
    memcpy(x86_cpu_def, def, sizeof(*def));
227

    
228
    featurestr = strtok(NULL, ",");
229

    
230
    while (featurestr) {
231
        char *val;
232
        if (featurestr[0] == '+') {
233
            add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features);
234
        } else if (featurestr[0] == '-') {
235
            add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features);
236
        } else if ((val = strchr(featurestr, '='))) {
237
            *val = 0; val++;
238
            if (!strcmp(featurestr, "family")) {
239
                char *err;
240
                family = strtol(val, &err, 10);
241
                if (!*val || *err || family < 0) {
242
                    fprintf(stderr, "bad numerical value %s\n", val);
243
                    x86_cpu_def = 0;
244
                    goto error;
245
                }
246
                x86_cpu_def->family = family;
247
            } else if (!strcmp(featurestr, "model")) {
248
                char *err;
249
                model = strtol(val, &err, 10);
250
                if (!*val || *err || model < 0 || model > 0xf) {
251
                    fprintf(stderr, "bad numerical value %s\n", val);
252
                    x86_cpu_def = 0;
253
                    goto error;
254
                }
255
                x86_cpu_def->model = model;
256
            } else if (!strcmp(featurestr, "stepping")) {
257
                char *err;
258
                stepping = strtol(val, &err, 10);
259
                if (!*val || *err || stepping < 0 || stepping > 0xf) {
260
                    fprintf(stderr, "bad numerical value %s\n", val);
261
                    x86_cpu_def = 0;
262
                    goto error;
263
                }
264
                x86_cpu_def->stepping = stepping;
265
            } else {
266
                fprintf(stderr, "unrecognized feature %s\n", featurestr);
267
                x86_cpu_def = 0;
268
                goto error;
269
            }
270
        } else {
271
            fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
272
            x86_cpu_def = 0;
273
            goto error;
274
        }
275
        featurestr = strtok(NULL, ",");
276
    }
277
    x86_cpu_def->features |= plus_features;
278
    x86_cpu_def->ext_features |= plus_ext_features;
279
    x86_cpu_def->ext2_features |= plus_ext2_features;
280
    x86_cpu_def->ext3_features |= plus_ext3_features;
281
    x86_cpu_def->features &= ~minus_features;
282
    x86_cpu_def->ext_features &= ~minus_ext_features;
283
    x86_cpu_def->ext2_features &= ~minus_ext2_features;
284
    x86_cpu_def->ext3_features &= ~minus_ext3_features;
285
    free(s);
286
    return 0;
287

    
288
error:
289
    free(s);
290
    return -1;
291
}
292

    
293
void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
294
{
295
    unsigned int i;
296

    
297
    for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++)
298
        (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
299
}
300

    
301
static int cpu_x86_register (CPUX86State *env, const char *cpu_model)
302
{
303
    x86_def_t def1, *def = &def1;
304

    
305
    if (cpu_x86_find_by_name(def, cpu_model) < 0)
306
        return -1;
307
    if (def->vendor1) {
308
        env->cpuid_vendor1 = def->vendor1;
309
        env->cpuid_vendor2 = def->vendor2;
310
        env->cpuid_vendor3 = def->vendor3;
311
    } else {
312
        env->cpuid_vendor1 = 0x756e6547; /* "Genu" */
313
        env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
314
        env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
315
    }
316
    env->cpuid_level = def->level;
317
    env->cpuid_version = (def->family << 8) | (def->model << 4) | def->stepping;
318
    env->cpuid_features = def->features;
319
    env->pat = 0x0007040600070406ULL;
320
    env->cpuid_ext_features = def->ext_features;
321
    env->cpuid_ext2_features = def->ext2_features;
322
    env->cpuid_xlevel = def->xlevel;
323
    env->cpuid_ext3_features = def->ext3_features;
324
    {
325
        const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
326
        int c, len, i;
327
        len = strlen(model_id);
328
        for(i = 0; i < 48; i++) {
329
            if (i >= len)
330
                c = '\0';
331
            else
332
                c = model_id[i];
333
            env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
334
        }
335
    }
336
    return 0;
337
}
338

    
339
/* NOTE: must be called outside the CPU execute loop */
340
void cpu_reset(CPUX86State *env)
341
{
342
    int i;
343

    
344
    memset(env, 0, offsetof(CPUX86State, breakpoints));
345

    
346
    tlb_flush(env, 1);
347

    
348
    env->old_exception = -1;
349

    
350
    /* init to reset state */
351

    
352
#ifdef CONFIG_SOFTMMU
353
    env->hflags |= HF_SOFTMMU_MASK;
354
#endif
355
    env->hflags |= HF_GIF_MASK;
356

    
357
    cpu_x86_update_cr0(env, 0x60000010);
358
    env->a20_mask = 0xffffffff;
359
    env->smbase = 0x30000;
360

    
361
    env->idt.limit = 0xffff;
362
    env->gdt.limit = 0xffff;
363
    env->ldt.limit = 0xffff;
364
    env->ldt.flags = DESC_P_MASK;
365
    env->tr.limit = 0xffff;
366
    env->tr.flags = DESC_P_MASK;
367

    
368
    cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, 0);
369
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, 0);
370
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, 0);
371
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, 0);
372
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, 0);
373
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0);
374

    
375
    env->eip = 0xfff0;
376
    env->regs[R_EDX] = env->cpuid_version;
377

    
378
    env->eflags = 0x2;
379

    
380
    /* FPU init */
381
    for(i = 0;i < 8; i++)
382
        env->fptags[i] = 1;
383
    env->fpuc = 0x37f;
384

    
385
    env->mxcsr = 0x1f80;
386
}
387

    
388
void cpu_x86_close(CPUX86State *env)
389
{
390
    free(env);
391
}
392

    
393
/***********************************************************/
394
/* x86 debug */
395

    
396
static const char *cc_op_str[] = {
397
    "DYNAMIC",
398
    "EFLAGS",
399

    
400
    "MULB",
401
    "MULW",
402
    "MULL",
403
    "MULQ",
404

    
405
    "ADDB",
406
    "ADDW",
407
    "ADDL",
408
    "ADDQ",
409

    
410
    "ADCB",
411
    "ADCW",
412
    "ADCL",
413
    "ADCQ",
414

    
415
    "SUBB",
416
    "SUBW",
417
    "SUBL",
418
    "SUBQ",
419

    
420
    "SBBB",
421
    "SBBW",
422
    "SBBL",
423
    "SBBQ",
424

    
425
    "LOGICB",
426
    "LOGICW",
427
    "LOGICL",
428
    "LOGICQ",
429

    
430
    "INCB",
431
    "INCW",
432
    "INCL",
433
    "INCQ",
434

    
435
    "DECB",
436
    "DECW",
437
    "DECL",
438
    "DECQ",
439

    
440
    "SHLB",
441
    "SHLW",
442
    "SHLL",
443
    "SHLQ",
444

    
445
    "SARB",
446
    "SARW",
447
    "SARL",
448
    "SARQ",
449
};
450

    
451
void cpu_dump_state(CPUState *env, FILE *f,
452
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
453
                    int flags)
454
{
455
    int eflags, i, nb;
456
    char cc_op_name[32];
457
    static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
458

    
459
    eflags = env->eflags;
460
#ifdef TARGET_X86_64
461
    if (env->hflags & HF_CS64_MASK) {
462
        cpu_fprintf(f,
463
                    "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n"
464
                    "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
465
                    "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
466
                    "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
467
                    "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
468
                    env->regs[R_EAX],
469
                    env->regs[R_EBX],
470
                    env->regs[R_ECX],
471
                    env->regs[R_EDX],
472
                    env->regs[R_ESI],
473
                    env->regs[R_EDI],
474
                    env->regs[R_EBP],
475
                    env->regs[R_ESP],
476
                    env->regs[8],
477
                    env->regs[9],
478
                    env->regs[10],
479
                    env->regs[11],
480
                    env->regs[12],
481
                    env->regs[13],
482
                    env->regs[14],
483
                    env->regs[15],
484
                    env->eip, eflags,
485
                    eflags & DF_MASK ? 'D' : '-',
486
                    eflags & CC_O ? 'O' : '-',
487
                    eflags & CC_S ? 'S' : '-',
488
                    eflags & CC_Z ? 'Z' : '-',
489
                    eflags & CC_A ? 'A' : '-',
490
                    eflags & CC_P ? 'P' : '-',
491
                    eflags & CC_C ? 'C' : '-',
492
                    env->hflags & HF_CPL_MASK,
493
                    (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
494
                    (env->a20_mask >> 20) & 1,
495
                    (env->hflags >> HF_SMM_SHIFT) & 1,
496
                    (env->hflags >> HF_HALTED_SHIFT) & 1);
497
    } else
498
#endif
499
    {
500
        cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
501
                    "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
502
                    "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
503
                    (uint32_t)env->regs[R_EAX],
504
                    (uint32_t)env->regs[R_EBX],
505
                    (uint32_t)env->regs[R_ECX],
506
                    (uint32_t)env->regs[R_EDX],
507
                    (uint32_t)env->regs[R_ESI],
508
                    (uint32_t)env->regs[R_EDI],
509
                    (uint32_t)env->regs[R_EBP],
510
                    (uint32_t)env->regs[R_ESP],
511
                    (uint32_t)env->eip, eflags,
512
                    eflags & DF_MASK ? 'D' : '-',
513
                    eflags & CC_O ? 'O' : '-',
514
                    eflags & CC_S ? 'S' : '-',
515
                    eflags & CC_Z ? 'Z' : '-',
516
                    eflags & CC_A ? 'A' : '-',
517
                    eflags & CC_P ? 'P' : '-',
518
                    eflags & CC_C ? 'C' : '-',
519
                    env->hflags & HF_CPL_MASK,
520
                    (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
521
                    (env->a20_mask >> 20) & 1,
522
                    (env->hflags >> HF_SMM_SHIFT) & 1,
523
                    (env->hflags >> HF_HALTED_SHIFT) & 1);
524
    }
525

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

    
658
/***********************************************************/
659
/* x86 mmu */
660
/* XXX: add PGE support */
661

    
662
void cpu_x86_set_a20(CPUX86State *env, int a20_state)
663
{
664
    a20_state = (a20_state != 0);
665
    if (a20_state != ((env->a20_mask >> 20) & 1)) {
666
#if defined(DEBUG_MMU)
667
        printf("A20 update: a20=%d\n", a20_state);
668
#endif
669
        /* if the cpu is currently executing code, we must unlink it and
670
           all the potentially executing TB */
671
        cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
672

    
673
        /* when a20 is changed, all the MMU mappings are invalid, so
674
           we must flush everything */
675
        tlb_flush(env, 1);
676
        env->a20_mask = 0xffefffff | (a20_state << 20);
677
    }
678
}
679

    
680
void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
681
{
682
    int pe_state;
683

    
684
#if defined(DEBUG_MMU)
685
    printf("CR0 update: CR0=0x%08x\n", new_cr0);
686
#endif
687
    if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
688
        (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
689
        tlb_flush(env, 1);
690
    }
691

    
692
#ifdef TARGET_X86_64
693
    if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
694
        (env->efer & MSR_EFER_LME)) {
695
        /* enter in long mode */
696
        /* XXX: generate an exception */
697
        if (!(env->cr[4] & CR4_PAE_MASK))
698
            return;
699
        env->efer |= MSR_EFER_LMA;
700
        env->hflags |= HF_LMA_MASK;
701
    } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
702
               (env->efer & MSR_EFER_LMA)) {
703
        /* exit long mode */
704
        env->efer &= ~MSR_EFER_LMA;
705
        env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
706
        env->eip &= 0xffffffff;
707
    }
708
#endif
709
    env->cr[0] = new_cr0 | CR0_ET_MASK;
710

    
711
    /* update PE flag in hidden flags */
712
    pe_state = (env->cr[0] & CR0_PE_MASK);
713
    env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
714
    /* ensure that ADDSEG is always set in real mode */
715
    env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
716
    /* update FPU flags */
717
    env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
718
        ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
719
}
720

    
721
/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
722
   the PDPT */
723
void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
724
{
725
    env->cr[3] = new_cr3;
726
    if (env->cr[0] & CR0_PG_MASK) {
727
#if defined(DEBUG_MMU)
728
        printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
729
#endif
730
        tlb_flush(env, 0);
731
    }
732
}
733

    
734
void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
735
{
736
#if defined(DEBUG_MMU)
737
    printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
738
#endif
739
    if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
740
        (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
741
        tlb_flush(env, 1);
742
    }
743
    /* SSE handling */
744
    if (!(env->cpuid_features & CPUID_SSE))
745
        new_cr4 &= ~CR4_OSFXSR_MASK;
746
    if (new_cr4 & CR4_OSFXSR_MASK)
747
        env->hflags |= HF_OSFXSR_MASK;
748
    else
749
        env->hflags &= ~HF_OSFXSR_MASK;
750

    
751
    env->cr[4] = new_cr4;
752
}
753

    
754
/* XXX: also flush 4MB pages */
755
void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr)
756
{
757
    tlb_flush_page(env, addr);
758
}
759

    
760
#if defined(CONFIG_USER_ONLY)
761

    
762
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
763
                             int is_write, int mmu_idx, int is_softmmu)
764
{
765
    /* user mode only emulation */
766
    is_write &= 1;
767
    env->cr[2] = addr;
768
    env->error_code = (is_write << PG_ERROR_W_BIT);
769
    env->error_code |= PG_ERROR_U_MASK;
770
    env->exception_index = EXCP0E_PAGE;
771
    return 1;
772
}
773

    
774
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
775
{
776
    return addr;
777
}
778

    
779
#else
780

    
781
#define PHYS_ADDR_MASK 0xfffff000
782

    
783
/* return value:
784
   -1 = cannot handle fault
785
   0  = nothing more to do
786
   1  = generate PF fault
787
   2  = soft MMU activation required for this block
788
*/
789
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
790
                             int is_write1, int mmu_idx, int is_softmmu)
791
{
792
    uint64_t ptep, pte;
793
    uint32_t pdpe_addr, pde_addr, pte_addr;
794
    int error_code, is_dirty, prot, page_size, ret, is_write, is_user;
795
    unsigned long paddr, page_offset;
796
    target_ulong vaddr, virt_addr;
797

    
798
    is_user = mmu_idx == MMU_USER_IDX;
799
#if defined(DEBUG_MMU)
800
    printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
801
           addr, is_write1, is_user, env->eip);
802
#endif
803
    is_write = is_write1 & 1;
804

    
805
    if (!(env->cr[0] & CR0_PG_MASK)) {
806
        pte = addr;
807
        virt_addr = addr & TARGET_PAGE_MASK;
808
        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
809
        page_size = 4096;
810
        goto do_mapping;
811
    }
812

    
813
    if (env->cr[4] & CR4_PAE_MASK) {
814
        uint64_t pde, pdpe;
815

    
816
        /* XXX: we only use 32 bit physical addresses */
817
#ifdef TARGET_X86_64
818
        if (env->hflags & HF_LMA_MASK) {
819
            uint32_t pml4e_addr;
820
            uint64_t pml4e;
821
            int32_t sext;
822

    
823
            /* test virtual address sign extension */
824
            sext = (int64_t)addr >> 47;
825
            if (sext != 0 && sext != -1) {
826
                env->error_code = 0;
827
                env->exception_index = EXCP0D_GPF;
828
                return 1;
829
            }
830

    
831
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
832
                env->a20_mask;
833
            pml4e = ldq_phys(pml4e_addr);
834
            if (!(pml4e & PG_PRESENT_MASK)) {
835
                error_code = 0;
836
                goto do_fault;
837
            }
838
            if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
839
                error_code = PG_ERROR_RSVD_MASK;
840
                goto do_fault;
841
            }
842
            if (!(pml4e & PG_ACCESSED_MASK)) {
843
                pml4e |= PG_ACCESSED_MASK;
844
                stl_phys_notdirty(pml4e_addr, pml4e);
845
            }
846
            ptep = pml4e ^ PG_NX_MASK;
847
            pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
848
                env->a20_mask;
849
            pdpe = ldq_phys(pdpe_addr);
850
            if (!(pdpe & PG_PRESENT_MASK)) {
851
                error_code = 0;
852
                goto do_fault;
853
            }
854
            if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
855
                error_code = PG_ERROR_RSVD_MASK;
856
                goto do_fault;
857
            }
858
            ptep &= pdpe ^ PG_NX_MASK;
859
            if (!(pdpe & PG_ACCESSED_MASK)) {
860
                pdpe |= PG_ACCESSED_MASK;
861
                stl_phys_notdirty(pdpe_addr, pdpe);
862
            }
863
        } else
864
#endif
865
        {
866
            /* XXX: load them when cr3 is loaded ? */
867
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
868
                env->a20_mask;
869
            pdpe = ldq_phys(pdpe_addr);
870
            if (!(pdpe & PG_PRESENT_MASK)) {
871
                error_code = 0;
872
                goto do_fault;
873
            }
874
            ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;
875
        }
876

    
877
        pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &
878
            env->a20_mask;
879
        pde = ldq_phys(pde_addr);
880
        if (!(pde & PG_PRESENT_MASK)) {
881
            error_code = 0;
882
            goto do_fault;
883
        }
884
        if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {
885
            error_code = PG_ERROR_RSVD_MASK;
886
            goto do_fault;
887
        }
888
        ptep &= pde ^ PG_NX_MASK;
889
        if (pde & PG_PSE_MASK) {
890
            /* 2 MB page */
891
            page_size = 2048 * 1024;
892
            ptep ^= PG_NX_MASK;
893
            if ((ptep & PG_NX_MASK) && is_write1 == 2)
894
                goto do_fault_protect;
895
            if (is_user) {
896
                if (!(ptep & PG_USER_MASK))
897
                    goto do_fault_protect;
898
                if (is_write && !(ptep & PG_RW_MASK))
899
                    goto do_fault_protect;
900
            } else {
901
                if ((env->cr[0] & CR0_WP_MASK) &&
902
                    is_write && !(ptep & PG_RW_MASK))
903
                    goto do_fault_protect;
904
            }
905
            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
906
            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
907
                pde |= PG_ACCESSED_MASK;
908
                if (is_dirty)
909
                    pde |= PG_DIRTY_MASK;
910
                stl_phys_notdirty(pde_addr, pde);
911
            }
912
            /* align to page_size */
913
            pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);
914
            virt_addr = addr & ~(page_size - 1);
915
        } else {
916
            /* 4 KB page */
917
            if (!(pde & PG_ACCESSED_MASK)) {
918
                pde |= PG_ACCESSED_MASK;
919
                stl_phys_notdirty(pde_addr, pde);
920
            }
921
            pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &
922
                env->a20_mask;
923
            pte = ldq_phys(pte_addr);
924
            if (!(pte & PG_PRESENT_MASK)) {
925
                error_code = 0;
926
                goto do_fault;
927
            }
928
            if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {
929
                error_code = PG_ERROR_RSVD_MASK;
930
                goto do_fault;
931
            }
932
            /* combine pde and pte nx, user and rw protections */
933
            ptep &= pte ^ PG_NX_MASK;
934
            ptep ^= PG_NX_MASK;
935
            if ((ptep & PG_NX_MASK) && is_write1 == 2)
936
                goto do_fault_protect;
937
            if (is_user) {
938
                if (!(ptep & PG_USER_MASK))
939
                    goto do_fault_protect;
940
                if (is_write && !(ptep & PG_RW_MASK))
941
                    goto do_fault_protect;
942
            } else {
943
                if ((env->cr[0] & CR0_WP_MASK) &&
944
                    is_write && !(ptep & PG_RW_MASK))
945
                    goto do_fault_protect;
946
            }
947
            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
948
            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
949
                pte |= PG_ACCESSED_MASK;
950
                if (is_dirty)
951
                    pte |= PG_DIRTY_MASK;
952
                stl_phys_notdirty(pte_addr, pte);
953
            }
954
            page_size = 4096;
955
            virt_addr = addr & ~0xfff;
956
            pte = pte & (PHYS_ADDR_MASK | 0xfff);
957
        }
958
    } else {
959
        uint32_t pde;
960

    
961
        /* page directory entry */
962
        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &
963
            env->a20_mask;
964
        pde = ldl_phys(pde_addr);
965
        if (!(pde & PG_PRESENT_MASK)) {
966
            error_code = 0;
967
            goto do_fault;
968
        }
969
        /* if PSE bit is set, then we use a 4MB page */
970
        if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
971
            page_size = 4096 * 1024;
972
            if (is_user) {
973
                if (!(pde & PG_USER_MASK))
974
                    goto do_fault_protect;
975
                if (is_write && !(pde & PG_RW_MASK))
976
                    goto do_fault_protect;
977
            } else {
978
                if ((env->cr[0] & CR0_WP_MASK) &&
979
                    is_write && !(pde & PG_RW_MASK))
980
                    goto do_fault_protect;
981
            }
982
            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
983
            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
984
                pde |= PG_ACCESSED_MASK;
985
                if (is_dirty)
986
                    pde |= PG_DIRTY_MASK;
987
                stl_phys_notdirty(pde_addr, pde);
988
            }
989

    
990
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
991
            ptep = pte;
992
            virt_addr = addr & ~(page_size - 1);
993
        } else {
994
            if (!(pde & PG_ACCESSED_MASK)) {
995
                pde |= PG_ACCESSED_MASK;
996
                stl_phys_notdirty(pde_addr, pde);
997
            }
998

    
999
            /* page directory entry */
1000
            pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &
1001
                env->a20_mask;
1002
            pte = ldl_phys(pte_addr);
1003
            if (!(pte & PG_PRESENT_MASK)) {
1004
                error_code = 0;
1005
                goto do_fault;
1006
            }
1007
            /* combine pde and pte user and rw protections */
1008
            ptep = pte & pde;
1009
            if (is_user) {
1010
                if (!(ptep & PG_USER_MASK))
1011
                    goto do_fault_protect;
1012
                if (is_write && !(ptep & PG_RW_MASK))
1013
                    goto do_fault_protect;
1014
            } else {
1015
                if ((env->cr[0] & CR0_WP_MASK) &&
1016
                    is_write && !(ptep & PG_RW_MASK))
1017
                    goto do_fault_protect;
1018
            }
1019
            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
1020
            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
1021
                pte |= PG_ACCESSED_MASK;
1022
                if (is_dirty)
1023
                    pte |= PG_DIRTY_MASK;
1024
                stl_phys_notdirty(pte_addr, pte);
1025
            }
1026
            page_size = 4096;
1027
            virt_addr = addr & ~0xfff;
1028
        }
1029
    }
1030
    /* the page can be put in the TLB */
1031
    prot = PAGE_READ;
1032
    if (!(ptep & PG_NX_MASK))
1033
        prot |= PAGE_EXEC;
1034
    if (pte & PG_DIRTY_MASK) {
1035
        /* only set write access if already dirty... otherwise wait
1036
           for dirty access */
1037
        if (is_user) {
1038
            if (ptep & PG_RW_MASK)
1039
                prot |= PAGE_WRITE;
1040
        } else {
1041
            if (!(env->cr[0] & CR0_WP_MASK) ||
1042
                (ptep & PG_RW_MASK))
1043
                prot |= PAGE_WRITE;
1044
        }
1045
    }
1046
 do_mapping:
1047
    pte = pte & env->a20_mask;
1048

    
1049
    /* Even if 4MB pages, we map only one 4KB page in the cache to
1050
       avoid filling it too fast */
1051
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
1052
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
1053
    vaddr = virt_addr + page_offset;
1054

    
1055
    ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
1056
    return ret;
1057
 do_fault_protect:
1058
    error_code = PG_ERROR_P_MASK;
1059
 do_fault:
1060
    error_code |= (is_write << PG_ERROR_W_BIT);
1061
    if (is_user)
1062
        error_code |= PG_ERROR_U_MASK;
1063
    if (is_write1 == 2 &&
1064
        (env->efer & MSR_EFER_NXE) &&
1065
        (env->cr[4] & CR4_PAE_MASK))
1066
        error_code |= PG_ERROR_I_D_MASK;
1067
    if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE)) {
1068
        stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), addr);
1069
    } else {
1070
        env->cr[2] = addr;
1071
    }
1072
    env->error_code = error_code;
1073
    env->exception_index = EXCP0E_PAGE;
1074
    /* the VMM will handle this */
1075
    if (INTERCEPTEDl(_exceptions, 1 << EXCP0E_PAGE))
1076
        return 2;
1077
    return 1;
1078
}
1079

    
1080
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1081
{
1082
    uint32_t pde_addr, pte_addr;
1083
    uint32_t pde, pte, paddr, page_offset, page_size;
1084

    
1085
    if (env->cr[4] & CR4_PAE_MASK) {
1086
        uint32_t pdpe_addr, pde_addr, pte_addr;
1087
        uint32_t pdpe;
1088

    
1089
        /* XXX: we only use 32 bit physical addresses */
1090
#ifdef TARGET_X86_64
1091
        if (env->hflags & HF_LMA_MASK) {
1092
            uint32_t pml4e_addr, pml4e;
1093
            int32_t sext;
1094

    
1095
            /* test virtual address sign extension */
1096
            sext = (int64_t)addr >> 47;
1097
            if (sext != 0 && sext != -1)
1098
                return -1;
1099

    
1100
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
1101
                env->a20_mask;
1102
            pml4e = ldl_phys(pml4e_addr);
1103
            if (!(pml4e & PG_PRESENT_MASK))
1104
                return -1;
1105

    
1106
            pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
1107
                env->a20_mask;
1108
            pdpe = ldl_phys(pdpe_addr);
1109
            if (!(pdpe & PG_PRESENT_MASK))
1110
                return -1;
1111
        } else
1112
#endif
1113
        {
1114
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
1115
                env->a20_mask;
1116
            pdpe = ldl_phys(pdpe_addr);
1117
            if (!(pdpe & PG_PRESENT_MASK))
1118
                return -1;
1119
        }
1120

    
1121
        pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
1122
            env->a20_mask;
1123
        pde = ldl_phys(pde_addr);
1124
        if (!(pde & PG_PRESENT_MASK)) {
1125
            return -1;
1126
        }
1127
        if (pde & PG_PSE_MASK) {
1128
            /* 2 MB page */
1129
            page_size = 2048 * 1024;
1130
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
1131
        } else {
1132
            /* 4 KB page */
1133
            pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
1134
                env->a20_mask;
1135
            page_size = 4096;
1136
            pte = ldl_phys(pte_addr);
1137
        }
1138
    } else {
1139
        if (!(env->cr[0] & CR0_PG_MASK)) {
1140
            pte = addr;
1141
            page_size = 4096;
1142
        } else {
1143
            /* page directory entry */
1144
            pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
1145
            pde = ldl_phys(pde_addr);
1146
            if (!(pde & PG_PRESENT_MASK))
1147
                return -1;
1148
            if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
1149
                pte = pde & ~0x003ff000; /* align to 4MB */
1150
                page_size = 4096 * 1024;
1151
            } else {
1152
                /* page directory entry */
1153
                pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
1154
                pte = ldl_phys(pte_addr);
1155
                if (!(pte & PG_PRESENT_MASK))
1156
                    return -1;
1157
                page_size = 4096;
1158
            }
1159
        }
1160
        pte = pte & env->a20_mask;
1161
    }
1162

    
1163
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
1164
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
1165
    return paddr;
1166
}
1167
#endif /* !CONFIG_USER_ONLY */