Statistics
| Branch: | Revision:

root / target-i386 / helper.c @ 262ffdae

History | View | Annotate | Download (39.6 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->hflags2 |= HF2_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 | (2 << DESC_TYPE_SHIFT);
387
    env->tr.limit = 0xffff;
388
    env->tr.flags = DESC_P_MASK | (11 < DESC_TYPE_SHIFT);
389

    
390
    cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
391
                           DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK | DESC_R_MASK);
392
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
393
                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
394
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
395
                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
396
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
397
                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
398
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
399
                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
400
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
401
                           DESC_P_MASK | DESC_S_MASK | DESC_W_MASK);
402

    
403
    env->eip = 0xfff0;
404
    env->regs[R_EDX] = env->cpuid_version;
405

    
406
    env->eflags = 0x2;
407

    
408
    /* FPU init */
409
    for(i = 0;i < 8; i++)
410
        env->fptags[i] = 1;
411
    env->fpuc = 0x37f;
412

    
413
    env->mxcsr = 0x1f80;
414
}
415

    
416
void cpu_x86_close(CPUX86State *env)
417
{
418
    free(env);
419
}
420

    
421
/***********************************************************/
422
/* x86 debug */
423

    
424
static const char *cc_op_str[] = {
425
    "DYNAMIC",
426
    "EFLAGS",
427

    
428
    "MULB",
429
    "MULW",
430
    "MULL",
431
    "MULQ",
432

    
433
    "ADDB",
434
    "ADDW",
435
    "ADDL",
436
    "ADDQ",
437

    
438
    "ADCB",
439
    "ADCW",
440
    "ADCL",
441
    "ADCQ",
442

    
443
    "SUBB",
444
    "SUBW",
445
    "SUBL",
446
    "SUBQ",
447

    
448
    "SBBB",
449
    "SBBW",
450
    "SBBL",
451
    "SBBQ",
452

    
453
    "LOGICB",
454
    "LOGICW",
455
    "LOGICL",
456
    "LOGICQ",
457

    
458
    "INCB",
459
    "INCW",
460
    "INCL",
461
    "INCQ",
462

    
463
    "DECB",
464
    "DECW",
465
    "DECL",
466
    "DECQ",
467

    
468
    "SHLB",
469
    "SHLW",
470
    "SHLL",
471
    "SHLQ",
472

    
473
    "SARB",
474
    "SARW",
475
    "SARL",
476
    "SARQ",
477
};
478

    
479
void cpu_dump_state(CPUState *env, FILE *f,
480
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
481
                    int flags)
482
{
483
    int eflags, i, nb;
484
    char cc_op_name[32];
485
    static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
486

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

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

    
686
/***********************************************************/
687
/* x86 mmu */
688
/* XXX: add PGE support */
689

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

    
701
        /* when a20 is changed, all the MMU mappings are invalid, so
702
           we must flush everything */
703
        tlb_flush(env, 1);
704
        env->a20_mask = (~0x100000) | (a20_state << 20);
705
    }
706
}
707

    
708
void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
709
{
710
    int pe_state;
711

    
712
#if defined(DEBUG_MMU)
713
    printf("CR0 update: CR0=0x%08x\n", new_cr0);
714
#endif
715
    if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
716
        (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
717
        tlb_flush(env, 1);
718
    }
719

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

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

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

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

    
779
    env->cr[4] = new_cr4;
780
}
781

    
782
/* XXX: also flush 4MB pages */
783
void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr)
784
{
785
    tlb_flush_page(env, addr);
786
}
787

    
788
#if defined(CONFIG_USER_ONLY)
789

    
790
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
791
                             int is_write, int mmu_idx, int is_softmmu)
792
{
793
    /* user mode only emulation */
794
    is_write &= 1;
795
    env->cr[2] = addr;
796
    env->error_code = (is_write << PG_ERROR_W_BIT);
797
    env->error_code |= PG_ERROR_U_MASK;
798
    env->exception_index = EXCP0E_PAGE;
799
    return 1;
800
}
801

    
802
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
803
{
804
    return addr;
805
}
806

    
807
#else
808

    
809
/* XXX: This value should match the one returned by CPUID
810
 * and in exec.c */
811
#if defined(USE_KQEMU)
812
#define PHYS_ADDR_MASK 0xfffff000L
813
#else
814
# if defined(TARGET_X86_64)
815
# define PHYS_ADDR_MASK 0xfffffff000L
816
# else
817
# define PHYS_ADDR_MASK 0xffffff000L
818
# endif
819
#endif
820

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

    
837
    is_user = mmu_idx == MMU_USER_IDX;
838
#if defined(DEBUG_MMU)
839
    printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
840
           addr, is_write1, is_user, env->eip);
841
#endif
842
    is_write = is_write1 & 1;
843

    
844
    if (!(env->cr[0] & CR0_PG_MASK)) {
845
        pte = addr;
846
        virt_addr = addr & TARGET_PAGE_MASK;
847
        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
848
        page_size = 4096;
849
        goto do_mapping;
850
    }
851

    
852
    if (env->cr[4] & CR4_PAE_MASK) {
853
        uint64_t pde, pdpe;
854
        target_ulong pdpe_addr;
855

    
856
#ifdef TARGET_X86_64
857
        if (env->hflags & HF_LMA_MASK) {
858
            uint64_t pml4e_addr, pml4e;
859
            int32_t sext;
860

    
861
            /* test virtual address sign extension */
862
            sext = (int64_t)addr >> 47;
863
            if (sext != 0 && sext != -1) {
864
                env->error_code = 0;
865
                env->exception_index = EXCP0D_GPF;
866
                return 1;
867
            }
868

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

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

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

    
1028
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
1029
            ptep = pte;
1030
            virt_addr = addr & ~(page_size - 1);
1031
        } else {
1032
            if (!(pde & PG_ACCESSED_MASK)) {
1033
                pde |= PG_ACCESSED_MASK;
1034
                stl_phys_notdirty(pde_addr, pde);
1035
            }
1036

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

    
1087
    /* Even if 4MB pages, we map only one 4KB page in the cache to
1088
       avoid filling it too fast */
1089
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
1090
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
1091
    vaddr = virt_addr + page_offset;
1092

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

    
1117
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1118
{
1119
    target_ulong pde_addr, pte_addr;
1120
    uint64_t pte;
1121
    target_phys_addr_t paddr;
1122
    uint32_t page_offset;
1123
    int page_size;
1124

    
1125
    if (env->cr[4] & CR4_PAE_MASK) {
1126
        target_ulong pdpe_addr;
1127
        uint64_t pde, pdpe;
1128

    
1129
#ifdef TARGET_X86_64
1130
        if (env->hflags & HF_LMA_MASK) {
1131
            uint64_t pml4e_addr, pml4e;
1132
            int32_t sext;
1133

    
1134
            /* test virtual address sign extension */
1135
            sext = (int64_t)addr >> 47;
1136
            if (sext != 0 && sext != -1)
1137
                return -1;
1138

    
1139
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
1140
                env->a20_mask;
1141
            pml4e = ldq_phys(pml4e_addr);
1142
            if (!(pml4e & PG_PRESENT_MASK))
1143
                return -1;
1144

    
1145
            pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
1146
                env->a20_mask;
1147
            pdpe = ldq_phys(pdpe_addr);
1148
            if (!(pdpe & PG_PRESENT_MASK))
1149
                return -1;
1150
        } else
1151
#endif
1152
        {
1153
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
1154
                env->a20_mask;
1155
            pdpe = ldq_phys(pdpe_addr);
1156
            if (!(pdpe & PG_PRESENT_MASK))
1157
                return -1;
1158
        }
1159

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

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

    
1204
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
1205
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
1206
    return paddr;
1207
}
1208
#endif /* !CONFIG_USER_ONLY */