Revision eaa728ee

b/Makefile.target
201 201
LIBOBJS+=fpu/softfloat-native.o
202 202
endif
203 203
CPPFLAGS+=-I$(SRC_PATH)/fpu
204

  
205
ifeq ($(TARGET_ARCH), i386)
206
LIBOBJS+=helper.o helper2.o
207
endif
208

  
209
ifeq ($(TARGET_ARCH), x86_64)
210
LIBOBJS+=helper.o helper2.o
211
endif
212

  
213
ifeq ($(TARGET_BASE_ARCH), ppc)
214
LIBOBJS+= op_helper.o helper.o
215
endif
216

  
217
ifeq ($(TARGET_BASE_ARCH), mips)
218
LIBOBJS+= op_helper.o helper.o
219
endif
220

  
221
ifeq ($(TARGET_BASE_ARCH), sparc)
222 204
LIBOBJS+= op_helper.o helper.o
223
endif
224 205

  
225 206
ifeq ($(TARGET_BASE_ARCH), arm)
226
LIBOBJS+= op_helper.o helper.o neon_helper.o iwmmxt_helper.o
227
endif
228

  
229
ifeq ($(TARGET_BASE_ARCH), sh4)
230
LIBOBJS+= op_helper.o helper.o
231
endif
232

  
233
ifeq ($(TARGET_BASE_ARCH), m68k)
234
LIBOBJS+= op_helper.o helper.o
207
LIBOBJS+= neon_helper.o iwmmxt_helper.o
235 208
endif
236 209

  
237 210
ifeq ($(TARGET_BASE_ARCH), alpha)
238
LIBOBJS+= op_helper.o helper.o alpha_palcode.o
211
LIBOBJS+= alpha_palcode.o
239 212
endif
240 213

  
241 214
ifeq ($(TARGET_BASE_ARCH), cris)
242
LIBOBJS+= op_helper.o helper.o
243 215
LIBOBJS+= cris-dis.o
244 216

  
245 217
ifndef CONFIG_USER_ONLY
......
323 295

  
324 296
# HELPER_CFLAGS is used for all the code compiled with static register
325 297
# variables
326
ifeq ($(TARGET_BASE_ARCH), i386)
327
# XXX: rename helper.c to op_helper.c
328
helper.o: helper.c
329
	$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(I386_CFLAGS) -c -o $@ $<
330
else
331 298
op_helper.o: op_helper.c
332
	$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
333
endif
299
	$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(I386_CFLAGS) -c -o $@ $<
334 300

  
335 301
cpu-exec.o: cpu-exec.c $(OPC_H)
336 302
	$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
b/target-i386/helper.c
1 1
/*
2
 *  i386 helpers
2
 *  i386 helpers (without register variable usage)
3 3
 *
4 4
 *  Copyright (c) 2003 Fabrice Bellard
5 5
 *
......
17 17
 * License along with this library; if not, write to the Free Software
18 18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 19
 */
20
#define CPU_NO_GLOBAL_REGS
21
#include "exec.h"
22
#include "host-utils.h"
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>
23 27

  
24
//#define DEBUG_PCALL
28
#include "cpu.h"
29
#include "exec-all.h"
30
#include "svm.h"
31
#include "qemu-common.h"
25 32

  
26
#if 0
27
#define raise_exception_err(a, b)\
28
do {\
29
    if (logfile)\
30
        fprintf(logfile, "raise_exception line=%d\n", __LINE__);\
31
    (raise_exception_err)(a, b);\
32
} while (0)
33
#endif
34

  
35
const uint8_t parity_table[256] = {
36
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
37
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
38
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
39
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
40
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
41
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
42
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
43
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
44
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
45
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
46
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
47
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
48
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
49
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
50
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
51
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
52
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
53
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
54
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
55
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
56
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
57
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
58
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
59
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
60
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
61
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
62
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
63
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
64
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
65
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
66
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
67
    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
68
};
33
//#define DEBUG_MMU
69 34

  
70
/* modulo 17 table */
71
const uint8_t rclw_table[32] = {
72
    0, 1, 2, 3, 4, 5, 6, 7,
73
    8, 9,10,11,12,13,14,15,
74
   16, 0, 1, 2, 3, 4, 5, 6,
75
    7, 8, 9,10,11,12,13,14,
76
};
35
static int cpu_x86_register (CPUX86State *env, const char *cpu_model);
77 36

  
78
/* modulo 9 table */
79
const uint8_t rclb_table[32] = {
80
    0, 1, 2, 3, 4, 5, 6, 7,
81
    8, 0, 1, 2, 3, 4, 5, 6,
82
    7, 8, 0, 1, 2, 3, 4, 5,
83
    6, 7, 8, 0, 1, 2, 3, 4,
84
};
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
}
85 93

  
86
const CPU86_LDouble f15rk[7] =
94
CPUX86State *cpu_x86_init(const char *cpu_model)
87 95
{
88
    0.00000000000000000000L,
89
    1.00000000000000000000L,
90
    3.14159265358979323851L,  /*pi*/
91
    0.30102999566398119523L,  /*lg2*/
92
    0.69314718055994530943L,  /*ln2*/
93
    1.44269504088896340739L,  /*l2e*/
94
    3.32192809488736234781L,  /*l2t*/
95
};
96
    CPUX86State *env;
97
    static int inited;
96 98

  
97
/* broken thread support */
99
    env = qemu_mallocz(sizeof(CPUX86State));
100
    if (!env)
101
        return NULL;
102
    cpu_exec_init(env);
103
    env->cpu_model_str = cpu_model;
98 104

  
99
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
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
};
100 227

  
101
void helper_lock(void)
228
static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
102 229
{
103
    spin_lock(&global_cpu_lock);
104
}
230
    unsigned int i;
231
    x86_def_t *def;
105 232

  
106
void helper_unlock(void)
107
{
108
    spin_unlock(&global_cpu_lock);
109
}
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;
110 238

  
111
void helper_write_eflags(target_ulong t0, uint32_t update_mask)
112
{
113
    load_eflags(t0, update_mask);
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;
114 313
}
115 314

  
116
target_ulong helper_read_eflags(void)
315
void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
117 316
{
118
    uint32_t eflags;
119
    eflags = cc_table[CC_OP].compute_all();
120
    eflags |= (DF & DF_MASK);
121
    eflags |= env->eflags & ~(VM_MASK | RF_MASK);
122
    return eflags;
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);
123 321
}
124 322

  
125
/* return non zero if error */
126
static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
127
                               int selector)
323
static int cpu_x86_register (CPUX86State *env, const char *cpu_model)
128 324
{
129
    SegmentCache *dt;
130
    int index;
131
    target_ulong ptr;
325
    x86_def_t def1, *def = &def1;
132 326

  
133
    if (selector & 0x4)
134
        dt = &env->ldt;
135
    else
136
        dt = &env->gdt;
137
    index = selector & ~7;
138
    if ((index + 7) > dt->limit)
327
    if (cpu_x86_find_by_name(def, cpu_model) < 0)
139 328
        return -1;
140
    ptr = dt->base + index;
141
    *e1_ptr = ldl_kernel(ptr);
142
    *e2_ptr = ldl_kernel(ptr + 4);
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
    }
143 358
    return 0;
144 359
}
145 360

  
146
static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
361
/* NOTE: must be called outside the CPU execute loop */
362
void cpu_reset(CPUX86State *env)
147 363
{
148
    unsigned int limit;
149
    limit = (e1 & 0xffff) | (e2 & 0x000f0000);
150
    if (e2 & DESC_G_MASK)
151
        limit = (limit << 12) | 0xfff;
152
    return limit;
153
}
364
    int i;
154 365

  
155
static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
156
{
157
    return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
158
}
366
    memset(env, 0, offsetof(CPUX86State, breakpoints));
159 367

  
160
static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
161
{
162
    sc->base = get_seg_base(e1, e2);
163
    sc->limit = get_seg_limit(e1, e2);
164
    sc->flags = e2;
165
}
368
    tlb_flush(env, 1);
166 369

  
167
/* init the segment cache in vm86 mode. */
168
static inline void load_seg_vm(int seg, int selector)
169
{
170
    selector &= 0xffff;
171
    cpu_x86_load_seg_cache(env, seg, selector,
172
                           (selector << 4), 0xffff, 0);
173
}
370
    env->old_exception = -1;
174 371

  
175
static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
176
                                       uint32_t *esp_ptr, int dpl)
177
{
178
    int type, index, shift;
372
    /* init to reset state */
179 373

  
180
#if 0
181
    {
182
        int i;
183
        printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
184
        for(i=0;i<env->tr.limit;i++) {
185
            printf("%02x ", env->tr.base[i]);
186
            if ((i & 7) == 7) printf("\n");
187
        }
188
        printf("\n");
189
    }
374
#ifdef CONFIG_SOFTMMU
375
    env->hflags |= HF_SOFTMMU_MASK;
190 376
#endif
377
    env->hflags |= HF_GIF_MASK;
191 378

  
192
    if (!(env->tr.flags & DESC_P_MASK))
193
        cpu_abort(env, "invalid tss");
194
    type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
195
    if ((type & 7) != 1)
196
        cpu_abort(env, "invalid tss type");
197
    shift = type >> 3;
198
    index = (dpl * 4 + 2) << shift;
199
    if (index + (4 << shift) - 1 > env->tr.limit)
200
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
201
    if (shift == 0) {
202
        *esp_ptr = lduw_kernel(env->tr.base + index);
203
        *ss_ptr = lduw_kernel(env->tr.base + index + 2);
204
    } else {
205
        *esp_ptr = ldl_kernel(env->tr.base + index);
206
        *ss_ptr = lduw_kernel(env->tr.base + index + 4);
207
    }
208
}
209

  
210
/* XXX: merge with load_seg() */
211
static void tss_load_seg(int seg_reg, int selector)
212
{
213
    uint32_t e1, e2;
214
    int rpl, dpl, cpl;
379
    cpu_x86_update_cr0(env, 0x60000010);
380
    env->a20_mask = ~0x0;
381
    env->smbase = 0x30000;
215 382

  
216
    if ((selector & 0xfffc) != 0) {
217
        if (load_segment(&e1, &e2, selector) != 0)
218
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
219
        if (!(e2 & DESC_S_MASK))
220
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
221
        rpl = selector & 3;
222
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
223
        cpl = env->hflags & HF_CPL_MASK;
224
        if (seg_reg == R_CS) {
225
            if (!(e2 & DESC_CS_MASK))
226
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
227
            /* XXX: is it correct ? */
228
            if (dpl != rpl)
229
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
230
            if ((e2 & DESC_C_MASK) && dpl > rpl)
231
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
232
        } else if (seg_reg == R_SS) {
233
            /* SS must be writable data */
234
            if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
235
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
236
            if (dpl != cpl || dpl != rpl)
237
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
238
        } else {
239
            /* not readable code */
240
            if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK))
241
                raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
242
            /* if data or non conforming code, checks the rights */
243
            if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) {
244
                if (dpl < cpl || dpl < rpl)
245
                    raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
246
            }
247
        }
248
        if (!(e2 & DESC_P_MASK))
249
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
250
        cpu_x86_load_seg_cache(env, seg_reg, selector,
251
                       get_seg_base(e1, e2),
252
                       get_seg_limit(e1, e2),
253
                       e2);
254
    } else {
255
        if (seg_reg == R_SS || seg_reg == R_CS)
256
            raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
257
    }
258
}
383
    env->idt.limit = 0xffff;
384
    env->gdt.limit = 0xffff;
385
    env->ldt.limit = 0xffff;
386
    env->ldt.flags = DESC_P_MASK;
387
    env->tr.limit = 0xffff;
388
    env->tr.flags = DESC_P_MASK;
259 389

  
260
#define SWITCH_TSS_JMP  0
261
#define SWITCH_TSS_IRET 1
262
#define SWITCH_TSS_CALL 2
390
    cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, 0);
391
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, 0);
392
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, 0);
393
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, 0);
394
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, 0);
395
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0);
263 396

  
264
/* XXX: restore CPU state in registers (PowerPC case) */
265
static void switch_tss(int tss_selector,
266
                       uint32_t e1, uint32_t e2, int source,
267
                       uint32_t next_eip)
268
{
269
    int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
270
    target_ulong tss_base;
271
    uint32_t new_regs[8], new_segs[6];
272
    uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
273
    uint32_t old_eflags, eflags_mask;
274
    SegmentCache *dt;
275
    int index;
276
    target_ulong ptr;
397
    env->eip = 0xfff0;
398
    env->regs[R_EDX] = env->cpuid_version;
277 399

  
278
    type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
279
#ifdef DEBUG_PCALL
280
    if (loglevel & CPU_LOG_PCALL)
281
        fprintf(logfile, "switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
282
#endif
400
    env->eflags = 0x2;
283 401

  
284
    /* if task gate, we read the TSS segment and we load it */
285
    if (type == 5) {
286
        if (!(e2 & DESC_P_MASK))
287
            raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
288
        tss_selector = e1 >> 16;
289
        if (tss_selector & 4)
290
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
291
        if (load_segment(&e1, &e2, tss_selector) != 0)
292
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
293
        if (e2 & DESC_S_MASK)
294
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
295
        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
296
        if ((type & 7) != 1)
297
            raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
298
    }
402
    /* FPU init */
403
    for(i = 0;i < 8; i++)
404
        env->fptags[i] = 1;
405
    env->fpuc = 0x37f;
299 406

  
300
    if (!(e2 & DESC_P_MASK))
301
        raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
407
    env->mxcsr = 0x1f80;
408
}
302 409

  
303
    if (type & 8)
304
        tss_limit_max = 103;
305
    else
306
        tss_limit_max = 43;
307
    tss_limit = get_seg_limit(e1, e2);
308
    tss_base = get_seg_base(e1, e2);
309
    if ((tss_selector & 4) != 0 ||
310
        tss_limit < tss_limit_max)
311
        raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
312
    old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
313
    if (old_type & 8)
314
        old_tss_limit_max = 103;
315
    else
316
        old_tss_limit_max = 43;
410
void cpu_x86_close(CPUX86State *env)
411
{
412
    free(env);
413
}
317 414

  
318
    /* read all the registers from the new TSS */
319
    if (type & 8) {
320
        /* 32 bit */
321
        new_cr3 = ldl_kernel(tss_base + 0x1c);
322
        new_eip = ldl_kernel(tss_base + 0x20);
323
        new_eflags = ldl_kernel(tss_base + 0x24);
324
        for(i = 0; i < 8; i++)
325
            new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
326
        for(i = 0; i < 6; i++)
327
            new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
328
        new_ldt = lduw_kernel(tss_base + 0x60);
329
        new_trap = ldl_kernel(tss_base + 0x64);
330
    } else {
331
        /* 16 bit */
332
        new_cr3 = 0;
333
        new_eip = lduw_kernel(tss_base + 0x0e);
334
        new_eflags = lduw_kernel(tss_base + 0x10);
335
        for(i = 0; i < 8; i++)
336
            new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
337
        for(i = 0; i < 4; i++)
338
            new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
339
        new_ldt = lduw_kernel(tss_base + 0x2a);
340
        new_segs[R_FS] = 0;
341
        new_segs[R_GS] = 0;
342
        new_trap = 0;
343
    }
415
/***********************************************************/
416
/* x86 debug */
344 417

  
345
    /* NOTE: we must avoid memory exceptions during the task switch,
346
       so we make dummy accesses before */
347
    /* XXX: it can still fail in some cases, so a bigger hack is
348
       necessary to valid the TLB after having done the accesses */
418
static const char *cc_op_str[] = {
419
    "DYNAMIC",
420
    "EFLAGS",
349 421

  
350
    v1 = ldub_kernel(env->tr.base);
351
    v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
352
    stb_kernel(env->tr.base, v1);
353
    stb_kernel(env->tr.base + old_tss_limit_max, v2);
422
    "MULB",
423
    "MULW",
424
    "MULL",
425
    "MULQ",
354 426

  
355
    /* clear busy bit (it is restartable) */
356
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
357
        target_ulong ptr;
358
        uint32_t e2;
359
        ptr = env->gdt.base + (env->tr.selector & ~7);
360
        e2 = ldl_kernel(ptr + 4);
361
        e2 &= ~DESC_TSS_BUSY_MASK;
362
        stl_kernel(ptr + 4, e2);
363
    }
364
    old_eflags = compute_eflags();
365
    if (source == SWITCH_TSS_IRET)
366
        old_eflags &= ~NT_MASK;
427
    "ADDB",
428
    "ADDW",
429
    "ADDL",
430
    "ADDQ",
367 431

  
368
    /* save the current state in the old TSS */
369
    if (type & 8) {
370
        /* 32 bit */
371
        stl_kernel(env->tr.base + 0x20, next_eip);
372
        stl_kernel(env->tr.base + 0x24, old_eflags);
373
        stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX);
374
        stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX);
375
        stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX);
376
        stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX);
377
        stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP);
378
        stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP);
379
        stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI);
380
        stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI);
381
        for(i = 0; i < 6; i++)
382
            stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
383
    } else {
384
        /* 16 bit */
385
        stw_kernel(env->tr.base + 0x0e, next_eip);
386
        stw_kernel(env->tr.base + 0x10, old_eflags);
387
        stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX);
388
        stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX);
389
        stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX);
390
        stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX);
391
        stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP);
392
        stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP);
393
        stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI);
394
        stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI);
395
        for(i = 0; i < 4; i++)
396
            stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
397
    }
432
    "ADCB",
433
    "ADCW",
434
    "ADCL",
435
    "ADCQ",
398 436

  
399
    /* now if an exception occurs, it will occurs in the next task
400
       context */
437
    "SUBB",
438
    "SUBW",
439
    "SUBL",
440
    "SUBQ",
401 441

  
402
    if (source == SWITCH_TSS_CALL) {
403
        stw_kernel(tss_base, env->tr.selector);
404
        new_eflags |= NT_MASK;
405
    }
442
    "SBBB",
443
    "SBBW",
444
    "SBBL",
445
    "SBBQ",
406 446

  
407
    /* set busy bit */
408
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
409
        target_ulong ptr;
410
        uint32_t e2;
411
        ptr = env->gdt.base + (tss_selector & ~7);
412
        e2 = ldl_kernel(ptr + 4);
413
        e2 |= DESC_TSS_BUSY_MASK;
414
        stl_kernel(ptr + 4, e2);
415
    }
447
    "LOGICB",
448
    "LOGICW",
449
    "LOGICL",
450
    "LOGICQ",
416 451

  
417
    /* set the new CPU state */
418
    /* from this point, any exception which occurs can give problems */
419
    env->cr[0] |= CR0_TS_MASK;
420
    env->hflags |= HF_TS_MASK;
421
    env->tr.selector = tss_selector;
422
    env->tr.base = tss_base;
423
    env->tr.limit = tss_limit;
424
    env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
452
    "INCB",
453
    "INCW",
454
    "INCL",
455
    "INCQ",
425 456

  
426
    if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
427
        cpu_x86_update_cr3(env, new_cr3);
428
    }
457
    "DECB",
458
    "DECW",
459
    "DECL",
460
    "DECQ",
429 461

  
430
    /* load all registers without an exception, then reload them with
431
       possible exception */
432
    env->eip = new_eip;
433
    eflags_mask = TF_MASK | AC_MASK | ID_MASK |
434
        IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
435
    if (!(type & 8))
436
        eflags_mask &= 0xffff;
437
    load_eflags(new_eflags, eflags_mask);
438
    /* XXX: what to do in 16 bit case ? */
439
    EAX = new_regs[0];
440
    ECX = new_regs[1];
441
    EDX = new_regs[2];
442
    EBX = new_regs[3];
443
    ESP = new_regs[4];
444
    EBP = new_regs[5];
445
    ESI = new_regs[6];
446
    EDI = new_regs[7];
447
    if (new_eflags & VM_MASK) {
448
        for(i = 0; i < 6; i++)
449
            load_seg_vm(i, new_segs[i]);
450
        /* in vm86, CPL is always 3 */
451
        cpu_x86_set_cpl(env, 3);
452
    } else {
453
        /* CPL is set the RPL of CS */
454
        cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
455
        /* first just selectors as the rest may trigger exceptions */
456
        for(i = 0; i < 6; i++)
457
            cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
458
    }
462
    "SHLB",
463
    "SHLW",
464
    "SHLL",
465
    "SHLQ",
459 466

  
460
    env->ldt.selector = new_ldt & ~4;
461
    env->ldt.base = 0;
462
    env->ldt.limit = 0;
463
    env->ldt.flags = 0;
467
    "SARB",
468
    "SARW",
469
    "SARL",
470
    "SARQ",
471
};
464 472

  
465
    /* load the LDT */
466
    if (new_ldt & 4)
467
        raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
473
void cpu_dump_state(CPUState *env, FILE *f,
474
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
475
                    int flags)
476
{
477
    int eflags, i, nb;
478
    char cc_op_name[32];
479
    static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
468 480

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

  
484
    /* load the segments */
485
    if (!(new_eflags & VM_MASK)) {
486
        tss_load_seg(R_CS, new_segs[R_CS]);
487
        tss_load_seg(R_SS, new_segs[R_SS]);
488
        tss_load_seg(R_ES, new_segs[R_ES]);
489
        tss_load_seg(R_DS, new_segs[R_DS]);
490
        tss_load_seg(R_FS, new_segs[R_FS]);
491
        tss_load_seg(R_GS, new_segs[R_GS]);
548
#ifdef TARGET_X86_64
549
    if (env->hflags & HF_LMA_MASK) {
550
        for(i = 0; i < 6; i++) {
551
            SegmentCache *sc = &env->segs[i];
552
            cpu_fprintf(f, "%s =%04x %016" PRIx64 " %08x %08x\n",
553
                        seg_name[i],
554
                        sc->selector,
555
                        sc->base,
556
                        sc->limit,
557
                        sc->flags);
558
        }
559
        cpu_fprintf(f, "LDT=%04x %016" PRIx64 " %08x %08x\n",
560
                    env->ldt.selector,
561
                    env->ldt.base,
562
                    env->ldt.limit,
563
                    env->ldt.flags);
564
        cpu_fprintf(f, "TR =%04x %016" PRIx64 " %08x %08x\n",
565
                    env->tr.selector,
566
                    env->tr.base,
567
                    env->tr.limit,
568
                    env->tr.flags);
569
        cpu_fprintf(f, "GDT=     %016" PRIx64 " %08x\n",
570
                    env->gdt.base, env->gdt.limit);
571
        cpu_fprintf(f, "IDT=     %016" PRIx64 " %08x\n",
572
                    env->idt.base, env->idt.limit);
573
        cpu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n",
574
                    (uint32_t)env->cr[0],
575
                    env->cr[2],
576
                    env->cr[3],
577
                    (uint32_t)env->cr[4]);
578
    } else
579
#endif
580
    {
581
        for(i = 0; i < 6; i++) {
582
            SegmentCache *sc = &env->segs[i];
583
            cpu_fprintf(f, "%s =%04x %08x %08x %08x\n",
584
                        seg_name[i],
585
                        sc->selector,
586
                        (uint32_t)sc->base,
587
                        sc->limit,
588
                        sc->flags);
589
        }
590
        cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n",
591
                    env->ldt.selector,
592
                    (uint32_t)env->ldt.base,
593
                    env->ldt.limit,
594
                    env->ldt.flags);
595
        cpu_fprintf(f, "TR =%04x %08x %08x %08x\n",
596
                    env->tr.selector,
597
                    (uint32_t)env->tr.base,
598
                    env->tr.limit,
599
                    env->tr.flags);
600
        cpu_fprintf(f, "GDT=     %08x %08x\n",
601
                    (uint32_t)env->gdt.base, env->gdt.limit);
602
        cpu_fprintf(f, "IDT=     %08x %08x\n",
603
                    (uint32_t)env->idt.base, env->idt.limit);
604
        cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n",
605
                    (uint32_t)env->cr[0],
606
                    (uint32_t)env->cr[2],
607
                    (uint32_t)env->cr[3],
608
                    (uint32_t)env->cr[4]);
609
    }
610
    if (flags & X86_DUMP_CCOP) {
611
        if ((unsigned)env->cc_op < CC_OP_NB)
612
            snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]);
613
        else
614
            snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
615
#ifdef TARGET_X86_64
616
        if (env->hflags & HF_CS64_MASK) {
617
            cpu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n",
618
                        env->cc_src, env->cc_dst,
619
                        cc_op_name);
620
        } else
621
#endif
622
        {
623
            cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
624
                        (uint32_t)env->cc_src, (uint32_t)env->cc_dst,
625
                        cc_op_name);
626
        }
492 627
    }
493

  
494
    /* check that EIP is in the CS segment limits */
495
    if (new_eip > env->segs[R_CS].limit) {
496
        /* XXX: different exception if CALL ? */
497
        raise_exception_err(EXCP0D_GPF, 0);
628
    if (flags & X86_DUMP_FPU) {
629
        int fptag;
630
        fptag = 0;
631
        for(i = 0; i < 8; i++) {
632
            fptag |= ((!env->fptags[i]) << i);
633
        }
634
        cpu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n",
635
                    env->fpuc,
636
                    (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11,
637
                    env->fpstt,
638
                    fptag,
639
                    env->mxcsr);
640
        for(i=0;i<8;i++) {
641
#if defined(USE_X86LDOUBLE)
642
            union {
643
                long double d;
644
                struct {
645
                    uint64_t lower;
646
                    uint16_t upper;
647
                } l;
648
            } tmp;
649
            tmp.d = env->fpregs[i].d;
650
            cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x",
651
                        i, tmp.l.lower, tmp.l.upper);
652
#else
653
            cpu_fprintf(f, "FPR%d=%016" PRIx64,
654
                        i, env->fpregs[i].mmx.q);
655
#endif
656
            if ((i & 1) == 1)
657
                cpu_fprintf(f, "\n");
658
            else
659
                cpu_fprintf(f, " ");
660
        }
661
        if (env->hflags & HF_CS64_MASK)
662
            nb = 16;
663
        else
664
            nb = 8;
665
        for(i=0;i<nb;i++) {
666
            cpu_fprintf(f, "XMM%02d=%08x%08x%08x%08x",
667
                        i,
668
                        env->xmm_regs[i].XMM_L(3),
669
                        env->xmm_regs[i].XMM_L(2),
670
                        env->xmm_regs[i].XMM_L(1),
671
                        env->xmm_regs[i].XMM_L(0));
672
            if ((i & 1) == 1)
673
                cpu_fprintf(f, "\n");
674
            else
675
                cpu_fprintf(f, " ");
676
        }
498 677
    }
499 678
}
500 679

  
501
/* check if Port I/O is allowed in TSS */
502
static inline void check_io(int addr, int size)
680
/***********************************************************/
681
/* x86 mmu */
682
/* XXX: add PGE support */
683

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

  
506
    /* TSS must be a valid 32 bit one */
507
    if (!(env->tr.flags & DESC_P_MASK) ||
508
        ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
509
        env->tr.limit < 103)
510
        goto fail;
511
    io_offset = lduw_kernel(env->tr.base + 0x66);
512
    io_offset += (addr >> 3);
513
    /* Note: the check needs two bytes */
514
    if ((io_offset + 1) > env->tr.limit)
515
        goto fail;
516
    val = lduw_kernel(env->tr.base + io_offset);
517
    val >>= (addr & 7);
518
    mask = (1 << size) - 1;
519
    /* all bits must be zero to allow the I/O */
520
    if ((val & mask) != 0) {
521
    fail:
522
        raise_exception_err(EXCP0D_GPF, 0);
695
        /* when a20 is changed, all the MMU mappings are invalid, so
696
           we must flush everything */
697
        tlb_flush(env, 1);
698
        env->a20_mask = (~0x100000) | (a20_state << 20);
523 699
    }
524 700
}
525 701

  
526
void helper_check_iob(uint32_t t0)
702
void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0)
527 703
{
528
    check_io(t0, 1);
529
}
704
    int pe_state;
530 705

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

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

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

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

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

  
556
target_ulong helper_inw(uint32_t port)
557
{
558
    return cpu_inw(env, port);
773
    env->cr[4] = new_cr4;
559 774
}
560 775

  
561
void helper_outl(uint32_t port, uint32_t data)
776
/* XXX: also flush 4MB pages */
777
void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr)
562 778
{
563
    cpu_outl(env, port, data);
779
    tlb_flush_page(env, addr);
564 780
}
565 781

  
566
target_ulong helper_inl(uint32_t port)
782
#if defined(CONFIG_USER_ONLY)
783

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

  
571
static inline unsigned int get_sp_mask(unsigned int e2)
796
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
572 797
{
573
    if (e2 & DESC_B_MASK)
574
        return 0xffffffff;
575
    else
576
        return 0xffff;
798
    return addr;
577 799
}
578 800

  
579
#ifdef TARGET_X86_64
580
#define SET_ESP(val, sp_mask)\
581
do {\
582
    if ((sp_mask) == 0xffff)\
583
        ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
584
    else if ((sp_mask) == 0xffffffffLL)\
585
        ESP = (uint32_t)(val);\
586
    else\
587
        ESP = (val);\
588
} while (0)
589 801
#else
590
#define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
591
#endif
592

  
593
/* XXX: add a is_user flag to have proper security support */
594
#define PUSHW(ssp, sp, sp_mask, val)\
595
{\
596
    sp -= 2;\
597
    stw_kernel((ssp) + (sp & (sp_mask)), (val));\
598
}
599

  
600
#define PUSHL(ssp, sp, sp_mask, val)\
601
{\
602
    sp -= 4;\
603
    stl_kernel((ssp) + (sp & (sp_mask)), (val));\
604
}
605 802

  
606
#define POPW(ssp, sp, sp_mask, val)\
607
{\
608
    val = lduw_kernel((ssp) + (sp & (sp_mask)));\
609
    sp += 2;\
610
}
611

  
612
#define POPL(ssp, sp, sp_mask, val)\
613
{\
614
    val = (uint32_t)ldl_kernel((ssp) + (sp & (sp_mask)));\
615
    sp += 4;\
616
}
617

  
618
/* protected mode interrupt */
619
static void do_interrupt_protected(int intno, int is_int, int error_code,
620
                                   unsigned int next_eip, int is_hw)
621
{
622
    SegmentCache *dt;
623
    target_ulong ptr, ssp;
624
    int type, dpl, selector, ss_dpl, cpl;
625
    int has_error_code, new_stack, shift;
626
    uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
627
    uint32_t old_eip, sp_mask;
628
    int svm_should_check = 1;
803
/* XXX: This value should match the one returned by CPUID
804
 * and in exec.c */
805
#if defined(USE_KQEMU)
806
#define PHYS_ADDR_MASK 0xfffff000L
807
#else
808
# if defined(TARGET_X86_64)
809
# define PHYS_ADDR_MASK 0xfffffff000L
810
# else
811
# define PHYS_ADDR_MASK 0xffffff000L
812
# endif
813
#endif
814

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

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

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

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

  
630
    if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) {
631
        next_eip = EIP;
632
        svm_should_check = 0;
633
    }
850
#ifdef TARGET_X86_64
851
        if (env->hflags & HF_LMA_MASK) {
852
            uint64_t pml4e_addr, pml4e;
853
            int32_t sext;
854

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

  
635
    if (svm_should_check
636
        && (INTERCEPTEDl(_exceptions, 1 << intno)
637
        && !is_int)) {
638
        raise_interrupt(intno, is_int, error_code, 0);
639
    }
640
    has_error_code = 0;
641
    if (!is_int && !is_hw) {
642
        switch(intno) {
643
        case 8:
644
        case 10:
645
        case 11:
646
        case 12:
647
        case 13:
648
        case 14:
649
        case 17:
650
            has_error_code = 1;
651
            break;
863
            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
864
                env->a20_mask;
865
            pml4e = ldq_phys(pml4e_addr);
866
            if (!(pml4e & PG_PRESENT_MASK)) {
867
                error_code = 0;
868
                goto do_fault;
869
            }
870
            if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {
871
                error_code = PG_ERROR_RSVD_MASK;
872
                goto do_fault;
873
            }
874
            if (!(pml4e & PG_ACCESSED_MASK)) {
875
                pml4e |= PG_ACCESSED_MASK;
876
                stl_phys_notdirty(pml4e_addr, pml4e);
877
            }
878
            ptep = pml4e ^ PG_NX_MASK;
879
            pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &
880
                env->a20_mask;
881
            pdpe = ldq_phys(pdpe_addr);
882
            if (!(pdpe & PG_PRESENT_MASK)) {
883
                error_code = 0;
884
                goto do_fault;
885
            }
886
            if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff