Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ 2157fa06

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

    
31
//#define DEBUG_MMU
32

    
33
#ifdef USE_CODE_COPY
34
#include <asm/ldt.h>
35
#include <linux/unistd.h>
36
#include <linux/version.h>
37

    
38
_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
39

    
40
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
41
#define modify_ldt_ldt_s user_desc
42
#endif
43
#endif /* USE_CODE_COPY */
44

    
45
CPUX86State *cpu_x86_init(void)
46
{
47
    CPUX86State *env;
48
    static int inited;
49

    
50
    cpu_exec_init();
51

    
52
    env = malloc(sizeof(CPUX86State));
53
    if (!env)
54
        return NULL;
55
    memset(env, 0, sizeof(CPUX86State));
56
    /* init various static tables */
57
    if (!inited) {
58
        inited = 1;
59
        optimize_flags_init();
60
    }
61
#ifdef USE_CODE_COPY
62
    /* testing code for code copy case */
63
    {
64
        struct modify_ldt_ldt_s ldt;
65

    
66
        ldt.entry_number = 1;
67
        ldt.base_addr = (unsigned long)env;
68
        ldt.limit = (sizeof(CPUState) + 0xfff) >> 12;
69
        ldt.seg_32bit = 1;
70
        ldt.contents = MODIFY_LDT_CONTENTS_DATA;
71
        ldt.read_exec_only = 0;
72
        ldt.limit_in_pages = 1;
73
        ldt.seg_not_present = 0;
74
        ldt.useable = 1;
75
        modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
76
        
77
        asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7));
78
    }
79
#endif
80
    {
81
        int family, model, stepping;
82
#ifdef TARGET_X86_64
83
        env->cpuid_vendor1 = 0x68747541; /* "Auth" */
84
        env->cpuid_vendor2 = 0x69746e65; /* "enti" */
85
        env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */
86
        family = 6;
87
        model = 2;
88
        stepping = 3;
89
#else
90
        env->cpuid_vendor1 = 0x756e6547; /* "Genu" */
91
        env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
92
        env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
93
#if 0
94
        /* pentium 75-200 */
95
        family = 5;
96
        model = 2;
97
        stepping = 11;
98
#else
99
        /* pentium pro */
100
        family = 6;
101
        model = 3;
102
        stepping = 3;
103
#endif
104
#endif
105
        env->cpuid_level = 2;
106
        env->cpuid_version = (family << 8) | (model << 4) | stepping;
107
        env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE |
108
                               CPUID_TSC | CPUID_MSR | CPUID_MCE |
109
                               CPUID_CX8 | CPUID_PGE | CPUID_CMOV);
110
        env->cpuid_ext_features = 0;
111
        env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | CPUID_PAE | CPUID_SEP;
112
        env->cpuid_xlevel = 0;
113
        {
114
            const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
115
            int c, len, i;
116
            len = strlen(model_id);
117
            for(i = 0; i < 48; i++) {
118
                if (i >= len)
119
                    c = '\0';
120
                else
121
                    c = model_id[i];
122
                env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
123
            }
124
        }
125
#ifdef TARGET_X86_64
126
        /* currently not enabled for std i386 because not fully tested */
127
        env->cpuid_features |= CPUID_APIC;
128
        env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF);
129
        env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL;
130
        env->cpuid_xlevel = 0x80000008;
131
#endif
132
    }
133
    cpu_single_env = env;
134
    cpu_reset(env);
135
#ifdef USE_KQEMU
136
    kqemu_init(env);
137
#endif
138
    return env;
139
}
140

    
141
/* NOTE: must be called outside the CPU execute loop */
142
void cpu_reset(CPUX86State *env)
143
{
144
    int i;
145

    
146
    memset(env, 0, offsetof(CPUX86State, breakpoints));
147

    
148
    tlb_flush(env, 1);
149

    
150
    /* init to reset state */
151

    
152
#ifdef CONFIG_SOFTMMU
153
    env->hflags |= HF_SOFTMMU_MASK;
154
#endif
155

    
156
    cpu_x86_update_cr0(env, 0x60000010);
157
    env->a20_mask = 0xffffffff;
158
    
159
    env->idt.limit = 0xffff;
160
    env->gdt.limit = 0xffff;
161
    env->ldt.limit = 0xffff;
162
    env->ldt.flags = DESC_P_MASK;
163
    env->tr.limit = 0xffff;
164
    env->tr.flags = DESC_P_MASK;
165
    
166
    cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, 0); 
167
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, 0);
168
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, 0);
169
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, 0);
170
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, 0);
171
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0);
172
    
173
    env->eip = 0xfff0;
174
    env->regs[R_EDX] = 0x600; /* indicate P6 processor */
175
    
176
    env->eflags = 0x2;
177
    
178
    /* FPU init */
179
    for(i = 0;i < 8; i++)
180
        env->fptags[i] = 1;
181
    env->fpuc = 0x37f;
182

    
183
    env->mxcsr = 0x1f80;
184
}
185

    
186
void cpu_x86_close(CPUX86State *env)
187
{
188
    free(env);
189
}
190

    
191
/***********************************************************/
192
/* x86 debug */
193

    
194
static const char *cc_op_str[] = {
195
    "DYNAMIC",
196
    "EFLAGS",
197

    
198
    "MULB",
199
    "MULW",
200
    "MULL",
201
    "MULQ",
202

    
203
    "ADDB",
204
    "ADDW",
205
    "ADDL",
206
    "ADDQ",
207

    
208
    "ADCB",
209
    "ADCW",
210
    "ADCL",
211
    "ADCQ",
212

    
213
    "SUBB",
214
    "SUBW",
215
    "SUBL",
216
    "SUBQ",
217

    
218
    "SBBB",
219
    "SBBW",
220
    "SBBL",
221
    "SBBQ",
222

    
223
    "LOGICB",
224
    "LOGICW",
225
    "LOGICL",
226
    "LOGICQ",
227

    
228
    "INCB",
229
    "INCW",
230
    "INCL",
231
    "INCQ",
232

    
233
    "DECB",
234
    "DECW",
235
    "DECL",
236
    "DECQ",
237

    
238
    "SHLB",
239
    "SHLW",
240
    "SHLL",
241
    "SHLQ",
242

    
243
    "SARB",
244
    "SARW",
245
    "SARL",
246
    "SARQ",
247
};
248

    
249
void cpu_dump_state(CPUState *env, FILE *f, 
250
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
251
                    int flags)
252
{
253
    int eflags, i, nb;
254
    char cc_op_name[32];
255
    static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
256

    
257
    eflags = env->eflags;
258
#ifdef TARGET_X86_64
259
    if (env->hflags & HF_CS64_MASK) {
260
        cpu_fprintf(f, 
261
                    "RAX=%016llx RBX=%016llx RCX=%016llx RDX=%016llx\n"
262
                    "RSI=%016llx RDI=%016llx RBP=%016llx RSP=%016llx\n"
263
                    "R8 =%016llx R9 =%016llx R10=%016llx R11=%016llx\n"
264
                    "R12=%016llx R13=%016llx R14=%016llx R15=%016llx\n"
265
                    "RIP=%016llx RFL=%08x [%c%c%c%c%c%c%c]    CPL=%d II=%d A20=%d\n",
266
                    env->regs[R_EAX], 
267
                    env->regs[R_EBX], 
268
                    env->regs[R_ECX], 
269
                    env->regs[R_EDX], 
270
                    env->regs[R_ESI], 
271
                    env->regs[R_EDI], 
272
                    env->regs[R_EBP], 
273
                    env->regs[R_ESP], 
274
                    env->regs[8], 
275
                    env->regs[9], 
276
                    env->regs[10], 
277
                    env->regs[11], 
278
                    env->regs[12], 
279
                    env->regs[13], 
280
                    env->regs[14], 
281
                    env->regs[15], 
282
                    env->eip, eflags,
283
                    eflags & DF_MASK ? 'D' : '-',
284
                    eflags & CC_O ? 'O' : '-',
285
                    eflags & CC_S ? 'S' : '-',
286
                    eflags & CC_Z ? 'Z' : '-',
287
                    eflags & CC_A ? 'A' : '-',
288
                    eflags & CC_P ? 'P' : '-',
289
                    eflags & CC_C ? 'C' : '-',
290
                    env->hflags & HF_CPL_MASK, 
291
                    (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
292
                    (env->a20_mask >> 20) & 1);
293
    } else 
294
#endif
295
    {
296
        cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
297
                    "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
298
                    "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]    CPL=%d II=%d A20=%d\n",
299
                    (uint32_t)env->regs[R_EAX], 
300
                    (uint32_t)env->regs[R_EBX], 
301
                    (uint32_t)env->regs[R_ECX], 
302
                    (uint32_t)env->regs[R_EDX], 
303
                    (uint32_t)env->regs[R_ESI], 
304
                    (uint32_t)env->regs[R_EDI], 
305
                    (uint32_t)env->regs[R_EBP], 
306
                    (uint32_t)env->regs[R_ESP], 
307
                    (uint32_t)env->eip, eflags,
308
                    eflags & DF_MASK ? 'D' : '-',
309
                    eflags & CC_O ? 'O' : '-',
310
                    eflags & CC_S ? 'S' : '-',
311
                    eflags & CC_Z ? 'Z' : '-',
312
                    eflags & CC_A ? 'A' : '-',
313
                    eflags & CC_P ? 'P' : '-',
314
                    eflags & CC_C ? 'C' : '-',
315
                    env->hflags & HF_CPL_MASK, 
316
                    (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
317
                    (env->a20_mask >> 20) & 1);
318
    }
319

    
320
#ifdef TARGET_X86_64
321
    if (env->hflags & HF_LMA_MASK) {
322
        for(i = 0; i < 6; i++) {
323
            SegmentCache *sc = &env->segs[i];
324
            cpu_fprintf(f, "%s =%04x %016llx %08x %08x\n",
325
                        seg_name[i],
326
                        sc->selector,
327
                        sc->base,
328
                        sc->limit,
329
                        sc->flags);
330
        }
331
        cpu_fprintf(f, "LDT=%04x %016llx %08x %08x\n",
332
                    env->ldt.selector,
333
                    env->ldt.base,
334
                    env->ldt.limit,
335
                    env->ldt.flags);
336
        cpu_fprintf(f, "TR =%04x %016llx %08x %08x\n",
337
                    env->tr.selector,
338
                    env->tr.base,
339
                    env->tr.limit,
340
                    env->tr.flags);
341
        cpu_fprintf(f, "GDT=     %016llx %08x\n",
342
                    env->gdt.base, env->gdt.limit);
343
        cpu_fprintf(f, "IDT=     %016llx %08x\n",
344
                    env->idt.base, env->idt.limit);
345
        cpu_fprintf(f, "CR0=%08x CR2=%016llx CR3=%016llx CR4=%08x\n",
346
                    (uint32_t)env->cr[0], 
347
                    env->cr[2], 
348
                    env->cr[3], 
349
                    (uint32_t)env->cr[4]);
350
    } else
351
#endif
352
    {
353
        for(i = 0; i < 6; i++) {
354
            SegmentCache *sc = &env->segs[i];
355
            cpu_fprintf(f, "%s =%04x %08x %08x %08x\n",
356
                        seg_name[i],
357
                        sc->selector,
358
                        (uint32_t)sc->base,
359
                        sc->limit,
360
                        sc->flags);
361
        }
362
        cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n",
363
                    env->ldt.selector,
364
                    (uint32_t)env->ldt.base,
365
                    env->ldt.limit,
366
                    env->ldt.flags);
367
        cpu_fprintf(f, "TR =%04x %08x %08x %08x\n",
368
                    env->tr.selector,
369
                    (uint32_t)env->tr.base,
370
                    env->tr.limit,
371
                    env->tr.flags);
372
        cpu_fprintf(f, "GDT=     %08x %08x\n",
373
                    (uint32_t)env->gdt.base, env->gdt.limit);
374
        cpu_fprintf(f, "IDT=     %08x %08x\n",
375
                    (uint32_t)env->idt.base, env->idt.limit);
376
        cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
377
                    (uint32_t)env->cr[0], 
378
                    (uint32_t)env->cr[2], 
379
                    (uint32_t)env->cr[3], 
380
                    (uint32_t)env->cr[4]);
381
    }
382
    if (flags & X86_DUMP_CCOP) {
383
        if ((unsigned)env->cc_op < CC_OP_NB)
384
            snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
385
        else
386
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
387
#ifdef TARGET_X86_64
388
        if (env->hflags & HF_CS64_MASK) {
389
            cpu_fprintf(f, "CCS=%016llx CCD=%016llx CCO=%-8s\n",
390
                        env->cc_src, env->cc_dst, 
391
                        cc_op_name);
392
        } else 
393
#endif
394
        {
395
            cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
396
                        (uint32_t)env->cc_src, (uint32_t)env->cc_dst, 
397
                        cc_op_name);
398
        }
399
    }
400
    if (flags & X86_DUMP_FPU) {
401
        int fptag;
402
        fptag = 0;
403
        for(i = 0; i < 8; i++) {
404
            fptag |= ((!env->fptags[i]) << i);
405
        }
406
        cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
407
                    env->fpuc,
408
                    (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
409
                    env->fpstt,
410
                    fptag,
411
                    env->mxcsr);
412
        for(i=0;i<8;i++) {
413
#if defined(USE_X86LDOUBLE)
414
            union {
415
                long double d;
416
                struct {
417
                    uint64_t lower;
418
                    uint16_t upper;
419
                } l;
420
            } tmp;
421
            tmp.d = env->fpregs[i].d;
422
            cpu_fprintf(f, "FPR%d=%016llx %04x",
423
                        i, tmp.l.lower, tmp.l.upper);
424
#else
425
            cpu_fprintf(f, "FPR%d=%016llx",
426
                        i, env->fpregs[i].mmx.q);
427
#endif
428
            if ((i & 1) == 1)
429
                cpu_fprintf(f, "\n");
430
            else
431
                cpu_fprintf(f, " ");
432
        }
433
        if (env->hflags & HF_CS64_MASK) 
434
            nb = 16;
435
        else
436
            nb = 8;
437
        for(i=0;i<nb;i++) {
438
            cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
439
                        i, 
440
                        env->xmm_regs[i].XMM_L(3),
441
                        env->xmm_regs[i].XMM_L(2),
442
                        env->xmm_regs[i].XMM_L(1),
443
                        env->xmm_regs[i].XMM_L(0));
444
            if ((i & 1) == 1)
445
                cpu_fprintf(f, "\n");
446
            else
447
                cpu_fprintf(f, " ");
448
        }
449
    }
450
}
451

    
452
/***********************************************************/
453
/* x86 mmu */
454
/* XXX: add PGE support */
455

    
456
void cpu_x86_set_a20(CPUX86State *env, int a20_state)
457
{
458
    a20_state = (a20_state != 0);
459
    if (a20_state != ((env->a20_mask >> 20) & 1)) {
460
#if defined(DEBUG_MMU)
461
        printf("A20 update: a20=%d\n", a20_state);
462
#endif
463
        /* if the cpu is currently executing code, we must unlink it and
464
           all the potentially executing TB */
465
        cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
466

    
467
        /* when a20 is changed, all the MMU mappings are invalid, so
468
           we must flush everything */
469
        tlb_flush(env, 1);
470
        env->a20_mask = 0xffefffff | (a20_state << 20);
471
    }
472
}
473

    
474
void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
475
{
476
    int pe_state;
477

    
478
#if defined(DEBUG_MMU)
479
    printf("CR0 update: CR0=0x%08x\n", new_cr0);
480
#endif
481
    if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
482
        (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
483
        tlb_flush(env, 1);
484
    }
485

    
486
#ifdef TARGET_X86_64
487
    if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
488
        (env->efer & MSR_EFER_LME)) {
489
        /* enter in long mode */
490
        /* XXX: generate an exception */
491
        if (!(env->cr[4] & CR4_PAE_MASK))
492
            return;
493
        env->efer |= MSR_EFER_LMA;
494
        env->hflags |= HF_LMA_MASK;
495
    } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
496
               (env->efer & MSR_EFER_LMA)) {
497
        /* exit long mode */
498
        env->efer &= ~MSR_EFER_LMA;
499
        env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
500
        env->eip &= 0xffffffff;
501
    }
502
#endif
503
    env->cr[0] = new_cr0 | CR0_ET_MASK;
504
    
505
    /* update PE flag in hidden flags */
506
    pe_state = (env->cr[0] & CR0_PE_MASK);
507
    env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
508
    /* ensure that ADDSEG is always set in real mode */
509
    env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
510
    /* update FPU flags */
511
    env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
512
        ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
513
}
514

    
515
/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
516
   the PDPT */
517
void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
518
{
519
    env->cr[3] = new_cr3;
520
    if (env->cr[0] & CR0_PG_MASK) {
521
#if defined(DEBUG_MMU)
522
        printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
523
#endif
524
        tlb_flush(env, 0);
525
    }
526
}
527

    
528
void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
529
{
530
#if defined(DEBUG_MMU)
531
    printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
532
#endif
533
    if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
534
        (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
535
        tlb_flush(env, 1);
536
    }
537
    /* SSE handling */
538
    if (!(env->cpuid_features & CPUID_SSE))
539
        new_cr4 &= ~CR4_OSFXSR_MASK;
540
    if (new_cr4 & CR4_OSFXSR_MASK)
541
        env->hflags |= HF_OSFXSR_MASK;
542
    else
543
        env->hflags &= ~HF_OSFXSR_MASK;
544

    
545
    env->cr[4] = new_cr4;
546
}
547

    
548
/* XXX: also flush 4MB pages */
549
void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
550
{
551
    tlb_flush_page(env, addr);
552
}
553

    
554
#if defined(CONFIG_USER_ONLY) 
555

    
556
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, 
557
                             int is_write, int is_user, int is_softmmu)
558
{
559
    /* user mode only emulation */
560
    is_write &= 1;
561
    env->cr[2] = addr;
562
    env->error_code = (is_write << PG_ERROR_W_BIT);
563
    env->error_code |= PG_ERROR_U_MASK;
564
    return 1;
565
}
566

    
567
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
568
{
569
    return addr;
570
}
571

    
572
#else
573

    
574
/* return value:
575
   -1 = cannot handle fault 
576
   0  = nothing more to do 
577
   1  = generate PF fault
578
   2  = soft MMU activation required for this block
579
*/
580
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, 
581
                             int is_write, int is_user, int is_softmmu)
582
{
583
    uint32_t pdpe_addr, pde_addr, pte_addr;
584
    uint32_t pde, pte, ptep, pdpe;
585
    int error_code, is_dirty, prot, page_size, ret;
586
    unsigned long paddr, page_offset;
587
    target_ulong vaddr, virt_addr;
588
    
589
#if defined(DEBUG_MMU)
590
    printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n", 
591
           addr, is_write, is_user, env->eip);
592
#endif
593
    is_write &= 1;
594
    
595
    if (!(env->cr[0] & CR0_PG_MASK)) {
596
        pte = addr;
597
        virt_addr = addr & TARGET_PAGE_MASK;
598
        prot = PAGE_READ | PAGE_WRITE;
599
        page_size = 4096;
600
        goto do_mapping;
601
    }
602

    
603
    if (env->cr[4] & CR4_PAE_MASK) {
604
        /* XXX: we only use 32 bit physical addresses */
605
#ifdef TARGET_X86_64
606
        if (env->hflags & HF_LMA_MASK) {
607
            uint32_t pml4e_addr, pml4e;
608
            int32_t sext;
609

    
610
            /* XXX: handle user + rw rights */
611
            /* XXX: handle NX flag */
612
            /* test virtual address sign extension */
613
            sext = (int64_t)addr >> 47;
614
            if (sext != 0 && sext != -1) {
615
                error_code = 0;
616
                goto do_fault;
617
            }
618
            
619
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) & 
620
                env->a20_mask;
621
            pml4e = ldl_phys(pml4e_addr);
622
            if (!(pml4e & PG_PRESENT_MASK)) {
623
                error_code = 0;
624
                goto do_fault;
625
            }
626
            if (!(pml4e & PG_ACCESSED_MASK)) {
627
                pml4e |= PG_ACCESSED_MASK;
628
                stl_phys_notdirty(pml4e_addr, pml4e);
629
            }
630
            
631
            pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) & 
632
                env->a20_mask;
633
            pdpe = ldl_phys(pdpe_addr);
634
            if (!(pdpe & PG_PRESENT_MASK)) {
635
                error_code = 0;
636
                goto do_fault;
637
            }
638
            if (!(pdpe & PG_ACCESSED_MASK)) {
639
                pdpe |= PG_ACCESSED_MASK;
640
                stl_phys_notdirty(pdpe_addr, pdpe);
641
            }
642
        } else 
643
#endif
644
        {
645
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) & 
646
                env->a20_mask;
647
            pdpe = ldl_phys(pdpe_addr);
648
            if (!(pdpe & PG_PRESENT_MASK)) {
649
                error_code = 0;
650
                goto do_fault;
651
            }
652
        }
653

    
654
        pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
655
            env->a20_mask;
656
        pde = ldl_phys(pde_addr);
657
        if (!(pde & PG_PRESENT_MASK)) {
658
            error_code = 0;
659
            goto do_fault;
660
        }
661
        if (pde & PG_PSE_MASK) {
662
            /* 2 MB page */
663
            page_size = 2048 * 1024;
664
            goto handle_big_page;
665
        } else {
666
            /* 4 KB page */
667
            if (!(pde & PG_ACCESSED_MASK)) {
668
                pde |= PG_ACCESSED_MASK;
669
                stl_phys_notdirty(pde_addr, pde);
670
            }
671
            pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
672
                env->a20_mask;
673
            goto handle_4k_page;
674
        }
675
    } else {
676
        /* page directory entry */
677
        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & 
678
            env->a20_mask;
679
        pde = ldl_phys(pde_addr);
680
        if (!(pde & PG_PRESENT_MASK)) {
681
            error_code = 0;
682
            goto do_fault;
683
        }
684
        /* if PSE bit is set, then we use a 4MB page */
685
        if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
686
            page_size = 4096 * 1024;
687
        handle_big_page:
688
            if (is_user) {
689
                if (!(pde & PG_USER_MASK))
690
                    goto do_fault_protect;
691
                if (is_write && !(pde & PG_RW_MASK))
692
                    goto do_fault_protect;
693
            } else {
694
                if ((env->cr[0] & CR0_WP_MASK) && 
695
                    is_write && !(pde & PG_RW_MASK)) 
696
                    goto do_fault_protect;
697
            }
698
            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
699
            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
700
                pde |= PG_ACCESSED_MASK;
701
                if (is_dirty)
702
                    pde |= PG_DIRTY_MASK;
703
                stl_phys_notdirty(pde_addr, pde);
704
            }
705
        
706
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
707
            ptep = pte;
708
            virt_addr = addr & ~(page_size - 1);
709
        } else {
710
            if (!(pde & PG_ACCESSED_MASK)) {
711
                pde |= PG_ACCESSED_MASK;
712
                stl_phys_notdirty(pde_addr, pde);
713
            }
714

    
715
            /* page directory entry */
716
            pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & 
717
                env->a20_mask;
718
        handle_4k_page:
719
            pte = ldl_phys(pte_addr);
720
            if (!(pte & PG_PRESENT_MASK)) {
721
                error_code = 0;
722
                goto do_fault;
723
            }
724
            /* combine pde and pte user and rw protections */
725
            ptep = pte & pde;
726
            if (is_user) {
727
                if (!(ptep & PG_USER_MASK))
728
                    goto do_fault_protect;
729
                if (is_write && !(ptep & PG_RW_MASK))
730
                    goto do_fault_protect;
731
            } else {
732
                if ((env->cr[0] & CR0_WP_MASK) &&
733
                    is_write && !(ptep & PG_RW_MASK)) 
734
                    goto do_fault_protect;
735
            }
736
            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
737
            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
738
                pte |= PG_ACCESSED_MASK;
739
                if (is_dirty)
740
                    pte |= PG_DIRTY_MASK;
741
                stl_phys_notdirty(pte_addr, pte);
742
            }
743
            page_size = 4096;
744
            virt_addr = addr & ~0xfff;
745
        }
746

    
747
        /* the page can be put in the TLB */
748
        prot = PAGE_READ;
749
        if (pte & PG_DIRTY_MASK) {
750
            /* only set write access if already dirty... otherwise wait
751
               for dirty access */
752
            if (is_user) {
753
                if (ptep & PG_RW_MASK)
754
                    prot |= PAGE_WRITE;
755
            } else {
756
                if (!(env->cr[0] & CR0_WP_MASK) ||
757
                    (ptep & PG_RW_MASK))
758
                    prot |= PAGE_WRITE;
759
            }
760
        }
761
    }
762
 do_mapping:
763
    pte = pte & env->a20_mask;
764

    
765
    /* Even if 4MB pages, we map only one 4KB page in the cache to
766
       avoid filling it too fast */
767
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
768
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
769
    vaddr = virt_addr + page_offset;
770
    
771
    ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
772
    return ret;
773
 do_fault_protect:
774
    error_code = PG_ERROR_P_MASK;
775
 do_fault:
776
    env->cr[2] = addr;
777
    env->error_code = (is_write << PG_ERROR_W_BIT) | error_code;
778
    if (is_user)
779
        env->error_code |= PG_ERROR_U_MASK;
780
    return 1;
781
}
782

    
783
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
784
{
785
    uint32_t pde_addr, pte_addr;
786
    uint32_t pde, pte, paddr, page_offset, page_size;
787

    
788
    if (env->cr[4] & CR4_PAE_MASK) {
789
        uint32_t pdpe_addr, pde_addr, pte_addr;
790
        uint32_t pdpe;
791

    
792
        /* XXX: we only use 32 bit physical addresses */
793
#ifdef TARGET_X86_64
794
        if (env->hflags & HF_LMA_MASK) {
795
            uint32_t pml4e_addr, pml4e;
796
            int32_t sext;
797

    
798
            /* test virtual address sign extension */
799
            sext = (int64_t)addr >> 47;
800
            if (sext != 0 && sext != -1)
801
                return -1;
802
            
803
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) & 
804
                env->a20_mask;
805
            pml4e = ldl_phys(pml4e_addr);
806
            if (!(pml4e & PG_PRESENT_MASK))
807
                return -1;
808
            
809
            pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) & 
810
                env->a20_mask;
811
            pdpe = ldl_phys(pdpe_addr);
812
            if (!(pdpe & PG_PRESENT_MASK))
813
                return -1;
814
        } else 
815
#endif
816
        {
817
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) & 
818
                env->a20_mask;
819
            pdpe = ldl_phys(pdpe_addr);
820
            if (!(pdpe & PG_PRESENT_MASK))
821
                return -1;
822
        }
823

    
824
        pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
825
            env->a20_mask;
826
        pde = ldl_phys(pde_addr);
827
        if (!(pde & PG_PRESENT_MASK)) {
828
            return -1;
829
        }
830
        if (pde & PG_PSE_MASK) {
831
            /* 2 MB page */
832
            page_size = 2048 * 1024;
833
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
834
        } else {
835
            /* 4 KB page */
836
            pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
837
                env->a20_mask;
838
            page_size = 4096;
839
            pte = ldl_phys(pte_addr);
840
        }
841
    } else {
842
        if (!(env->cr[0] & CR0_PG_MASK)) {
843
            pte = addr;
844
            page_size = 4096;
845
        } else {
846
            /* page directory entry */
847
            pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask;
848
            pde = ldl_phys(pde_addr);
849
            if (!(pde & PG_PRESENT_MASK)) 
850
                return -1;
851
            if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
852
                pte = pde & ~0x003ff000; /* align to 4MB */
853
                page_size = 4096 * 1024;
854
            } else {
855
                /* page directory entry */
856
                pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
857
                pte = ldl_phys(pte_addr);
858
                if (!(pte & PG_PRESENT_MASK))
859
                    return -1;
860
                page_size = 4096;
861
            }
862
        }
863
        pte = pte & env->a20_mask;
864
    }
865

    
866
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
867
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
868
    return paddr;
869
}
870
#endif /* !CONFIG_USER_ONLY */
871

    
872
#if defined(USE_CODE_COPY)
873
struct fpstate {
874
    uint16_t fpuc;
875
    uint16_t dummy1;
876
    uint16_t fpus;
877
    uint16_t dummy2;
878
    uint16_t fptag;
879
    uint16_t dummy3;
880

    
881
    uint32_t fpip;
882
    uint32_t fpcs;
883
    uint32_t fpoo;
884
    uint32_t fpos;
885
    uint8_t fpregs1[8 * 10];
886
};
887

    
888
void restore_native_fp_state(CPUState *env)
889
{
890
    int fptag, i, j;
891
    struct fpstate fp1, *fp = &fp1;
892
    
893
    fp->fpuc = env->fpuc;
894
    fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
895
    fptag = 0;
896
    for (i=7; i>=0; i--) {
897
        fptag <<= 2;
898
        if (env->fptags[i]) {
899
            fptag |= 3;
900
        } else {
901
            /* the FPU automatically computes it */
902
        }
903
    }
904
    fp->fptag = fptag;
905
    j = env->fpstt;
906
    for(i = 0;i < 8; i++) {
907
        memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
908
        j = (j + 1) & 7;
909
    }
910
    asm volatile ("frstor %0" : "=m" (*fp));
911
    env->native_fp_regs = 1;
912
}
913
 
914
void save_native_fp_state(CPUState *env)
915
{
916
    int fptag, i, j;
917
    uint16_t fpuc;
918
    struct fpstate fp1, *fp = &fp1;
919

    
920
    asm volatile ("fsave %0" : : "m" (*fp));
921
    env->fpuc = fp->fpuc;
922
    env->fpstt = (fp->fpus >> 11) & 7;
923
    env->fpus = fp->fpus & ~0x3800;
924
    fptag = fp->fptag;
925
    for(i = 0;i < 8; i++) {
926
        env->fptags[i] = ((fptag & 3) == 3);
927
        fptag >>= 2;
928
    }
929
    j = env->fpstt;
930
    for(i = 0;i < 8; i++) {
931
        memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
932
        j = (j + 1) & 7;
933
    }
934
    /* we must restore the default rounding state */
935
    /* XXX: we do not restore the exception state */
936
    fpuc = 0x037f | (env->fpuc & (3 << 10));
937
    asm volatile("fldcw %0" : : "m" (fpuc));
938
    env->native_fp_regs = 0;
939
}
940
#endif