Statistics
| Branch: | Revision:

root / target-i386 / helper2.c @ 5516d670

History | View | Annotate | Download (26.9 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_version = (family << 8) | (model << 4) | stepping;
106
        env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE |
107
                               CPUID_TSC | CPUID_MSR | CPUID_MCE |
108
                               CPUID_CX8 | CPUID_PGE | CPUID_CMOV);
109
        env->cpuid_ext_features = 0;
110
        env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | CPUID_PAE | CPUID_SEP;
111
#ifdef TARGET_X86_64
112
        /* currently not enabled for std i386 because not fully tested */
113
        env->cpuid_features |= CPUID_APIC;
114
#endif
115
    }
116
    cpu_single_env = env;
117
    cpu_reset(env);
118
#ifdef USE_KQEMU
119
    kqemu_init(env);
120
#endif
121
    return env;
122
}
123

    
124
/* NOTE: must be called outside the CPU execute loop */
125
void cpu_reset(CPUX86State *env)
126
{
127
    int i;
128

    
129
    memset(env, 0, offsetof(CPUX86State, breakpoints));
130

    
131
    tlb_flush(env, 1);
132

    
133
    /* init to reset state */
134

    
135
#ifdef CONFIG_SOFTMMU
136
    env->hflags |= HF_SOFTMMU_MASK;
137
#endif
138

    
139
    cpu_x86_update_cr0(env, 0x60000010);
140
    env->a20_mask = 0xffffffff;
141
    
142
    env->idt.limit = 0xffff;
143
    env->gdt.limit = 0xffff;
144
    env->ldt.limit = 0xffff;
145
    env->ldt.flags = DESC_P_MASK;
146
    env->tr.limit = 0xffff;
147
    env->tr.flags = DESC_P_MASK;
148
    
149
    cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, 0); 
150
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, 0);
151
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, 0);
152
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, 0);
153
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, 0);
154
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0);
155
    
156
    env->eip = 0xfff0;
157
    env->regs[R_EDX] = 0x600; /* indicate P6 processor */
158
    
159
    env->eflags = 0x2;
160
    
161
    /* FPU init */
162
    for(i = 0;i < 8; i++)
163
        env->fptags[i] = 1;
164
    env->fpuc = 0x37f;
165

    
166
    env->mxcsr = 0x1f80;
167
}
168

    
169
void cpu_x86_close(CPUX86State *env)
170
{
171
    free(env);
172
}
173

    
174
/***********************************************************/
175
/* x86 debug */
176

    
177
static const char *cc_op_str[] = {
178
    "DYNAMIC",
179
    "EFLAGS",
180

    
181
    "MULB",
182
    "MULW",
183
    "MULL",
184
    "MULQ",
185

    
186
    "ADDB",
187
    "ADDW",
188
    "ADDL",
189
    "ADDQ",
190

    
191
    "ADCB",
192
    "ADCW",
193
    "ADCL",
194
    "ADCQ",
195

    
196
    "SUBB",
197
    "SUBW",
198
    "SUBL",
199
    "SUBQ",
200

    
201
    "SBBB",
202
    "SBBW",
203
    "SBBL",
204
    "SBBQ",
205

    
206
    "LOGICB",
207
    "LOGICW",
208
    "LOGICL",
209
    "LOGICQ",
210

    
211
    "INCB",
212
    "INCW",
213
    "INCL",
214
    "INCQ",
215

    
216
    "DECB",
217
    "DECW",
218
    "DECL",
219
    "DECQ",
220

    
221
    "SHLB",
222
    "SHLW",
223
    "SHLL",
224
    "SHLQ",
225

    
226
    "SARB",
227
    "SARW",
228
    "SARL",
229
    "SARQ",
230
};
231

    
232
void cpu_dump_state(CPUState *env, FILE *f, 
233
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
234
                    int flags)
235
{
236
    int eflags, i;
237
    char cc_op_name[32];
238
    static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
239

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

    
303
#ifdef TARGET_X86_64
304
    if (env->hflags & HF_LMA_MASK) {
305
        for(i = 0; i < 6; i++) {
306
            SegmentCache *sc = &env->segs[i];
307
            cpu_fprintf(f, "%s =%04x %016llx %08x %08x\n",
308
                        seg_name[i],
309
                        sc->selector,
310
                        sc->base,
311
                        sc->limit,
312
                        sc->flags);
313
        }
314
        cpu_fprintf(f, "LDT=%04x %016llx %08x %08x\n",
315
                    env->ldt.selector,
316
                    env->ldt.base,
317
                    env->ldt.limit,
318
                    env->ldt.flags);
319
        cpu_fprintf(f, "TR =%04x %016llx %08x %08x\n",
320
                    env->tr.selector,
321
                    env->tr.base,
322
                    env->tr.limit,
323
                    env->tr.flags);
324
        cpu_fprintf(f, "GDT=     %016llx %08x\n",
325
                    env->gdt.base, env->gdt.limit);
326
        cpu_fprintf(f, "IDT=     %016llx %08x\n",
327
                    env->idt.base, env->idt.limit);
328
        cpu_fprintf(f, "CR0=%08x CR2=%016llx CR3=%016llx CR4=%08x\n",
329
                    (uint32_t)env->cr[0], 
330
                    env->cr[2], 
331
                    env->cr[3], 
332
                    (uint32_t)env->cr[4]);
333
    } else
334
#endif
335
    {
336
        for(i = 0; i < 6; i++) {
337
            SegmentCache *sc = &env->segs[i];
338
            cpu_fprintf(f, "%s =%04x %08x %08x %08x\n",
339
                        seg_name[i],
340
                        sc->selector,
341
                        (uint32_t)sc->base,
342
                        sc->limit,
343
                        sc->flags);
344
        }
345
        cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n",
346
                    env->ldt.selector,
347
                    (uint32_t)env->ldt.base,
348
                    env->ldt.limit,
349
                    env->ldt.flags);
350
        cpu_fprintf(f, "TR =%04x %08x %08x %08x\n",
351
                    env->tr.selector,
352
                    (uint32_t)env->tr.base,
353
                    env->tr.limit,
354
                    env->tr.flags);
355
        cpu_fprintf(f, "GDT=     %08x %08x\n",
356
                    (uint32_t)env->gdt.base, env->gdt.limit);
357
        cpu_fprintf(f, "IDT=     %08x %08x\n",
358
                    (uint32_t)env->idt.base, env->idt.limit);
359
        cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
360
                    (uint32_t)env->cr[0], 
361
                    (uint32_t)env->cr[2], 
362
                    (uint32_t)env->cr[3], 
363
                    (uint32_t)env->cr[4]);
364
    }
365
    if (flags & X86_DUMP_CCOP) {
366
        if ((unsigned)env->cc_op < CC_OP_NB)
367
            snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
368
        else
369
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
370
#ifdef TARGET_X86_64
371
        if (env->hflags & HF_CS64_MASK) {
372
            cpu_fprintf(f, "CCS=%016llx CCD=%016llx CCO=%-8s\n",
373
                        env->cc_src, env->cc_dst, 
374
                        cc_op_name);
375
        } else 
376
#endif
377
        {
378
            cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
379
                        (uint32_t)env->cc_src, (uint32_t)env->cc_dst, 
380
                        cc_op_name);
381
        }
382
    }
383
    if (flags & X86_DUMP_FPU) {
384
        cpu_fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
385
                (double)env->fpregs[0].d, 
386
                (double)env->fpregs[1].d, 
387
                (double)env->fpregs[2].d, 
388
                (double)env->fpregs[3].d);
389
        cpu_fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", 
390
                (double)env->fpregs[4].d, 
391
                (double)env->fpregs[5].d, 
392
                (double)env->fpregs[7].d, 
393
                (double)env->fpregs[8].d);
394
    }
395
}
396

    
397
/***********************************************************/
398
/* x86 mmu */
399
/* XXX: add PGE support */
400

    
401
void cpu_x86_set_a20(CPUX86State *env, int a20_state)
402
{
403
    a20_state = (a20_state != 0);
404
    if (a20_state != ((env->a20_mask >> 20) & 1)) {
405
#if defined(DEBUG_MMU)
406
        printf("A20 update: a20=%d\n", a20_state);
407
#endif
408
        /* if the cpu is currently executing code, we must unlink it and
409
           all the potentially executing TB */
410
        cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
411

    
412
        /* when a20 is changed, all the MMU mappings are invalid, so
413
           we must flush everything */
414
        tlb_flush(env, 1);
415
        env->a20_mask = 0xffefffff | (a20_state << 20);
416
    }
417
}
418

    
419
void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
420
{
421
    int pe_state;
422

    
423
#if defined(DEBUG_MMU)
424
    printf("CR0 update: CR0=0x%08x\n", new_cr0);
425
#endif
426
    if ((new_cr0 & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK)) !=
427
        (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) {
428
        tlb_flush(env, 1);
429
    }
430

    
431
#ifdef TARGET_X86_64
432
    if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) &&
433
        (env->efer & MSR_EFER_LME)) {
434
        /* enter in long mode */
435
        /* XXX: generate an exception */
436
        if (!(env->cr[4] & CR4_PAE_MASK))
437
            return;
438
        env->efer |= MSR_EFER_LMA;
439
        env->hflags |= HF_LMA_MASK;
440
    } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) &&
441
               (env->efer & MSR_EFER_LMA)) {
442
        /* exit long mode */
443
        env->efer &= ~MSR_EFER_LMA;
444
        env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
445
        env->eip &= 0xffffffff;
446
    }
447
#endif
448
    env->cr[0] = new_cr0 | CR0_ET_MASK;
449
    
450
    /* update PE flag in hidden flags */
451
    pe_state = (env->cr[0] & CR0_PE_MASK);
452
    env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
453
    /* ensure that ADDSEG is always set in real mode */
454
    env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT);
455
    /* update FPU flags */
456
    env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
457
        ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
458
}
459

    
460
/* XXX: in legacy PAE mode, generate a GPF if reserved bits are set in
461
   the PDPT */
462
void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3)
463
{
464
    env->cr[3] = new_cr3;
465
    if (env->cr[0] & CR0_PG_MASK) {
466
#if defined(DEBUG_MMU)
467
        printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3);
468
#endif
469
        tlb_flush(env, 0);
470
    }
471
}
472

    
473
void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4)
474
{
475
#if defined(DEBUG_MMU)
476
    printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]);
477
#endif
478
    if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) !=
479
        (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) {
480
        tlb_flush(env, 1);
481
    }
482
    /* SSE handling */
483
    if (!(env->cpuid_features & CPUID_SSE))
484
        new_cr4 &= ~CR4_OSFXSR_MASK;
485
    if (new_cr4 & CR4_OSFXSR_MASK)
486
        env->hflags |= HF_OSFXSR_MASK;
487
    else
488
        env->hflags &= ~HF_OSFXSR_MASK;
489

    
490
    env->cr[4] = new_cr4;
491
}
492

    
493
/* XXX: also flush 4MB pages */
494
void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
495
{
496
    tlb_flush_page(env, addr);
497
}
498

    
499
#if defined(CONFIG_USER_ONLY) 
500

    
501
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, 
502
                             int is_write, int is_user, int is_softmmu)
503
{
504
    /* user mode only emulation */
505
    is_write &= 1;
506
    env->cr[2] = addr;
507
    env->error_code = (is_write << PG_ERROR_W_BIT);
508
    env->error_code |= PG_ERROR_U_MASK;
509
    return 1;
510
}
511

    
512
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
513
{
514
    return addr;
515
}
516

    
517
#else
518

    
519
/* return value:
520
   -1 = cannot handle fault 
521
   0  = nothing more to do 
522
   1  = generate PF fault
523
   2  = soft MMU activation required for this block
524
*/
525
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, 
526
                             int is_write, int is_user, int is_softmmu)
527
{
528
    uint32_t pdpe_addr, pde_addr, pte_addr;
529
    uint32_t pde, pte, ptep, pdpe;
530
    int error_code, is_dirty, prot, page_size, ret;
531
    unsigned long paddr, page_offset;
532
    target_ulong vaddr, virt_addr;
533
    
534
#if defined(DEBUG_MMU)
535
    printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n", 
536
           addr, is_write, is_user, env->eip);
537
#endif
538
    is_write &= 1;
539
    
540
    if (!(env->cr[0] & CR0_PG_MASK)) {
541
        pte = addr;
542
        virt_addr = addr & TARGET_PAGE_MASK;
543
        prot = PAGE_READ | PAGE_WRITE;
544
        page_size = 4096;
545
        goto do_mapping;
546
    }
547

    
548
    if (env->cr[4] & CR4_PAE_MASK) {
549
        /* XXX: we only use 32 bit physical addresses */
550
#ifdef TARGET_X86_64
551
        if (env->hflags & HF_LMA_MASK) {
552
            uint32_t pml4e_addr, pml4e;
553
            int32_t sext;
554

    
555
            /* XXX: handle user + rw rights */
556
            /* XXX: handle NX flag */
557
            /* test virtual address sign extension */
558
            sext = (int64_t)addr >> 47;
559
            if (sext != 0 && sext != -1) {
560
                error_code = 0;
561
                goto do_fault;
562
            }
563
            
564
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) & 
565
                env->a20_mask;
566
            pml4e = ldl_phys(pml4e_addr);
567
            if (!(pml4e & PG_PRESENT_MASK)) {
568
                error_code = 0;
569
                goto do_fault;
570
            }
571
            if (!(pml4e & PG_ACCESSED_MASK)) {
572
                pml4e |= PG_ACCESSED_MASK;
573
                stl_phys_notdirty(pml4e_addr, pml4e);
574
            }
575
            
576
            pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) & 
577
                env->a20_mask;
578
            pdpe = ldl_phys(pdpe_addr);
579
            if (!(pdpe & PG_PRESENT_MASK)) {
580
                error_code = 0;
581
                goto do_fault;
582
            }
583
            if (!(pdpe & PG_ACCESSED_MASK)) {
584
                pdpe |= PG_ACCESSED_MASK;
585
                stl_phys_notdirty(pdpe_addr, pdpe);
586
            }
587
        } else 
588
#endif
589
        {
590
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) & 
591
                env->a20_mask;
592
            pdpe = ldl_phys(pdpe_addr);
593
            if (!(pdpe & PG_PRESENT_MASK)) {
594
                error_code = 0;
595
                goto do_fault;
596
            }
597
        }
598

    
599
        pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
600
            env->a20_mask;
601
        pde = ldl_phys(pde_addr);
602
        if (!(pde & PG_PRESENT_MASK)) {
603
            error_code = 0;
604
            goto do_fault;
605
        }
606
        if (pde & PG_PSE_MASK) {
607
            /* 2 MB page */
608
            page_size = 2048 * 1024;
609
            goto handle_big_page;
610
        } else {
611
            /* 4 KB page */
612
            if (!(pde & PG_ACCESSED_MASK)) {
613
                pde |= PG_ACCESSED_MASK;
614
                stl_phys_notdirty(pde_addr, pde);
615
            }
616
            pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
617
                env->a20_mask;
618
            goto handle_4k_page;
619
        }
620
    } else {
621
        /* page directory entry */
622
        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & 
623
            env->a20_mask;
624
        pde = ldl_phys(pde_addr);
625
        if (!(pde & PG_PRESENT_MASK)) {
626
            error_code = 0;
627
            goto do_fault;
628
        }
629
        /* if PSE bit is set, then we use a 4MB page */
630
        if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
631
            page_size = 4096 * 1024;
632
        handle_big_page:
633
            if (is_user) {
634
                if (!(pde & PG_USER_MASK))
635
                    goto do_fault_protect;
636
                if (is_write && !(pde & PG_RW_MASK))
637
                    goto do_fault_protect;
638
            } else {
639
                if ((env->cr[0] & CR0_WP_MASK) && 
640
                    is_write && !(pde & PG_RW_MASK)) 
641
                    goto do_fault_protect;
642
            }
643
            is_dirty = is_write && !(pde & PG_DIRTY_MASK);
644
            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
645
                pde |= PG_ACCESSED_MASK;
646
                if (is_dirty)
647
                    pde |= PG_DIRTY_MASK;
648
                stl_phys_notdirty(pde_addr, pde);
649
            }
650
        
651
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
652
            ptep = pte;
653
            virt_addr = addr & ~(page_size - 1);
654
        } else {
655
            if (!(pde & PG_ACCESSED_MASK)) {
656
                pde |= PG_ACCESSED_MASK;
657
                stl_phys_notdirty(pde_addr, pde);
658
            }
659

    
660
            /* page directory entry */
661
            pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & 
662
                env->a20_mask;
663
        handle_4k_page:
664
            pte = ldl_phys(pte_addr);
665
            if (!(pte & PG_PRESENT_MASK)) {
666
                error_code = 0;
667
                goto do_fault;
668
            }
669
            /* combine pde and pte user and rw protections */
670
            ptep = pte & pde;
671
            if (is_user) {
672
                if (!(ptep & PG_USER_MASK))
673
                    goto do_fault_protect;
674
                if (is_write && !(ptep & PG_RW_MASK))
675
                    goto do_fault_protect;
676
            } else {
677
                if ((env->cr[0] & CR0_WP_MASK) &&
678
                    is_write && !(ptep & PG_RW_MASK)) 
679
                    goto do_fault_protect;
680
            }
681
            is_dirty = is_write && !(pte & PG_DIRTY_MASK);
682
            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
683
                pte |= PG_ACCESSED_MASK;
684
                if (is_dirty)
685
                    pte |= PG_DIRTY_MASK;
686
                stl_phys_notdirty(pte_addr, pte);
687
            }
688
            page_size = 4096;
689
            virt_addr = addr & ~0xfff;
690
        }
691

    
692
        /* the page can be put in the TLB */
693
        prot = PAGE_READ;
694
        if (pte & PG_DIRTY_MASK) {
695
            /* only set write access if already dirty... otherwise wait
696
               for dirty access */
697
            if (is_user) {
698
                if (ptep & PG_RW_MASK)
699
                    prot |= PAGE_WRITE;
700
            } else {
701
                if (!(env->cr[0] & CR0_WP_MASK) ||
702
                    (ptep & PG_RW_MASK))
703
                    prot |= PAGE_WRITE;
704
            }
705
        }
706
    }
707
 do_mapping:
708
    pte = pte & env->a20_mask;
709

    
710
    /* Even if 4MB pages, we map only one 4KB page in the cache to
711
       avoid filling it too fast */
712
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
713
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
714
    vaddr = virt_addr + page_offset;
715
    
716
    ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
717
    return ret;
718
 do_fault_protect:
719
    error_code = PG_ERROR_P_MASK;
720
 do_fault:
721
    env->cr[2] = addr;
722
    env->error_code = (is_write << PG_ERROR_W_BIT) | error_code;
723
    if (is_user)
724
        env->error_code |= PG_ERROR_U_MASK;
725
    return 1;
726
}
727

    
728
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
729
{
730
    uint32_t pde_addr, pte_addr;
731
    uint32_t pde, pte, paddr, page_offset, page_size;
732

    
733
    if (env->cr[4] & CR4_PAE_MASK) {
734
        uint32_t pdpe_addr, pde_addr, pte_addr;
735
        uint32_t pdpe;
736

    
737
        /* XXX: we only use 32 bit physical addresses */
738
#ifdef TARGET_X86_64
739
        if (env->hflags & HF_LMA_MASK) {
740
            uint32_t pml4e_addr, pml4e;
741
            int32_t sext;
742

    
743
            /* test virtual address sign extension */
744
            sext = (int64_t)addr >> 47;
745
            if (sext != 0 && sext != -1)
746
                return -1;
747
            
748
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) & 
749
                env->a20_mask;
750
            pml4e = ldl_phys(pml4e_addr);
751
            if (!(pml4e & PG_PRESENT_MASK))
752
                return -1;
753
            
754
            pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) & 
755
                env->a20_mask;
756
            pdpe = ldl_phys(pdpe_addr);
757
            if (!(pdpe & PG_PRESENT_MASK))
758
                return -1;
759
        } else 
760
#endif
761
        {
762
            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) & 
763
                env->a20_mask;
764
            pdpe = ldl_phys(pdpe_addr);
765
            if (!(pdpe & PG_PRESENT_MASK))
766
                return -1;
767
        }
768

    
769
        pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
770
            env->a20_mask;
771
        pde = ldl_phys(pde_addr);
772
        if (!(pde & PG_PRESENT_MASK)) {
773
            return -1;
774
        }
775
        if (pde & PG_PSE_MASK) {
776
            /* 2 MB page */
777
            page_size = 2048 * 1024;
778
            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */
779
        } else {
780
            /* 4 KB page */
781
            pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
782
                env->a20_mask;
783
            page_size = 4096;
784
            pte = ldl_phys(pte_addr);
785
        }
786
    } else {
787
        if (!(env->cr[0] & CR0_PG_MASK)) {
788
            pte = addr;
789
            page_size = 4096;
790
        } else {
791
            /* page directory entry */
792
            pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask;
793
            pde = ldl_phys(pde_addr);
794
            if (!(pde & PG_PRESENT_MASK)) 
795
                return -1;
796
            if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
797
                pte = pde & ~0x003ff000; /* align to 4MB */
798
                page_size = 4096 * 1024;
799
            } else {
800
                /* page directory entry */
801
                pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask;
802
                pte = ldl_phys(pte_addr);
803
                if (!(pte & PG_PRESENT_MASK))
804
                    return -1;
805
                page_size = 4096;
806
            }
807
        }
808
        pte = pte & env->a20_mask;
809
    }
810

    
811
    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
812
    paddr = (pte & TARGET_PAGE_MASK) + page_offset;
813
    return paddr;
814
}
815
#endif /* !CONFIG_USER_ONLY */
816

    
817
#if defined(USE_CODE_COPY)
818
struct fpstate {
819
    uint16_t fpuc;
820
    uint16_t dummy1;
821
    uint16_t fpus;
822
    uint16_t dummy2;
823
    uint16_t fptag;
824
    uint16_t dummy3;
825

    
826
    uint32_t fpip;
827
    uint32_t fpcs;
828
    uint32_t fpoo;
829
    uint32_t fpos;
830
    uint8_t fpregs1[8 * 10];
831
};
832

    
833
void restore_native_fp_state(CPUState *env)
834
{
835
    int fptag, i, j;
836
    struct fpstate fp1, *fp = &fp1;
837
    
838
    fp->fpuc = env->fpuc;
839
    fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
840
    fptag = 0;
841
    for (i=7; i>=0; i--) {
842
        fptag <<= 2;
843
        if (env->fptags[i]) {
844
            fptag |= 3;
845
        } else {
846
            /* the FPU automatically computes it */
847
        }
848
    }
849
    fp->fptag = fptag;
850
    j = env->fpstt;
851
    for(i = 0;i < 8; i++) {
852
        memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
853
        j = (j + 1) & 7;
854
    }
855
    asm volatile ("frstor %0" : "=m" (*fp));
856
    env->native_fp_regs = 1;
857
}
858
 
859
void save_native_fp_state(CPUState *env)
860
{
861
    int fptag, i, j;
862
    uint16_t fpuc;
863
    struct fpstate fp1, *fp = &fp1;
864

    
865
    asm volatile ("fsave %0" : : "m" (*fp));
866
    env->fpuc = fp->fpuc;
867
    env->fpstt = (fp->fpus >> 11) & 7;
868
    env->fpus = fp->fpus & ~0x3800;
869
    fptag = fp->fptag;
870
    for(i = 0;i < 8; i++) {
871
        env->fptags[i] = ((fptag & 3) == 3);
872
        fptag >>= 2;
873
    }
874
    j = env->fpstt;
875
    for(i = 0;i < 8; i++) {
876
        memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
877
        j = (j + 1) & 7;
878
    }
879
    /* we must restore the default rounding state */
880
    /* XXX: we do not restore the exception state */
881
    fpuc = 0x037f | (env->fpuc & (3 << 10));
882
    asm volatile("fldcw %0" : : "m" (fpuc));
883
    env->native_fp_regs = 0;
884
}
885
#endif