Revision a049de61 target-i386/helper2.c

b/target-i386/helper2.c
47 47
#endif
48 48
#endif /* USE_CODE_COPY */
49 49

  
50
static struct x86_def_t *x86_cpu_def;
51
typedef struct x86_def_t x86_def_t;
52
static int cpu_x86_register (CPUX86State *env, const x86_def_t *def);
53

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

  
88
    for ( i = 0 ; i < 32 ; i++ ) 
89
        if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
90
            *features |= 1 << i;
91
            return;
92
        }
93
    for ( i = 0 ; i < 32 ; i++ ) 
94
        if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) {
95
            *ext_features |= 1 << i;
96
            return;
97
        }
98
    for ( i = 0 ; i < 32 ; i++ ) 
99
        if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) {
100
            *ext2_features |= 1 << i;
101
            return;
102
        }
103
    for ( i = 0 ; i < 32 ; i++ ) 
104
        if (ext3_features[i] && !strcmp (flagname, ext3_feature_name[i])) {
105
            *ext3_features |= 1 << i;
106
            return;
107
        }
108
    fprintf(stderr, "CPU feature %s not found\n", flagname);
109
}
110

  
50 111
CPUX86State *cpu_x86_init(void)
51 112
{
52 113
    CPUX86State *env;
......
81 142
        asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7));
82 143
    }
83 144
#endif
84
    {
85
        int family, model, stepping;
86
#ifdef TARGET_X86_64
87
        env->cpuid_vendor1 = 0x68747541; /* "Auth" */
88
        env->cpuid_vendor2 = 0x69746e65; /* "enti" */
89
        env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */
90
        family = 6;
91
        model = 2;
92
        stepping = 3;
93
#else
94
        env->cpuid_vendor1 = 0x756e6547; /* "Genu" */
95
        env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
96
        env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
97
#if 0
98
        /* pentium 75-200 */
99
        family = 5;
100
        model = 2;
101
        stepping = 11;
102
#else
103
        /* pentium pro */
104
        family = 6;
105
        model = 3;
106
        stepping = 3;
107
#endif
145
    cpu_x86_register(env, x86_cpu_def);
146
    cpu_reset(env);
147
#ifdef USE_KQEMU
148
    kqemu_init(env);
108 149
#endif
109
        env->cpuid_level = 2;
110
        env->cpuid_version = (family << 8) | (model << 4) | stepping;
111
        env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE |
112
                               CPUID_TSC | CPUID_MSR | CPUID_MCE |
113
                               CPUID_CX8 | CPUID_PGE | CPUID_CMOV |
114
                               CPUID_PAT);
115
        env->pat = 0x0007040600070406ULL;
116
        env->cpuid_ext3_features = CPUID_EXT3_SVM;
117
        env->cpuid_ext_features = CPUID_EXT_SSE3;
118
        env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | CPUID_PAE | CPUID_SEP;
119
        env->cpuid_features |= CPUID_APIC;
120
        env->cpuid_xlevel = 0x8000000e;
121
        {
122
            const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
123
            int c, len, i;
124
            len = strlen(model_id);
125
            for(i = 0; i < 48; i++) {
126
                if (i >= len)
127
                    c = '\0';
128
                else
129
                    c = model_id[i];
130
                env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
131
            }
132
        }
133
#ifdef TARGET_X86_64
134
        /* currently not enabled for std i386 because not fully tested */
135
        env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF);
136
        env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX;
150
    return env;
151
}
152

  
153
struct x86_def_t {
154
    const char *name;
155
    uint32_t vendor1, vendor2, vendor3;
156
    int family;
157
    int model;
158
    int stepping;
159
    uint32_t features, ext_features, ext2_features, ext3_features;
160
    uint32_t xlevel;
161
};
137 162

  
163
#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
164
          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
165
          CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
166
          CPUID_PAE | CPUID_SEP | CPUID_APIC)
167
static x86_def_t x86_defs[] = {
168
#ifdef TARGET_X86_64
169
    {
170
        .name = "qemu64",
171
        .vendor1 = 0x68747541, /* "Auth" */
172
        .vendor2 = 0x69746e65, /* "enti" */
173
        .vendor3 = 0x444d4163, /* "cAMD" */
174
        .family = 6,
175
        .model = 2,
176
        .stepping = 3,
177
        .features = PPRO_FEATURES | 
138 178
        /* these features are needed for Win64 and aren't fully implemented */
139
        env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA;
179
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
140 180
        /* this feature is needed for Solaris and isn't fully implemented */
141
        env->cpuid_features |= CPUID_PSE36;
181
            CPUID_PSE36,
182
        .ext_features = CPUID_EXT_SSE3,
183
        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 
184
            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
185
        .ext3_features = CPUID_EXT3_SVM,
186
        .xlevel = 0x80000008,
187
    },
142 188
#endif
189
    {
190
        .name = "qemu32",
191
        .family = 6,
192
        .model = 3,
193
        .stepping = 3,
194
        .features = PPRO_FEATURES,
195
        .ext_features = CPUID_EXT_SSE3,
196
        .xlevel = 0,
197
    },
198
    {
199
        .name = "486",
200
        .family = 4,
201
        .model = 0,
202
        .stepping = 0,
203
        .features = 0x0000000B,
204
        .xlevel = 0,
205
    },
206
    {
207
        .name = "pentium",
208
        .family = 5,
209
        .model = 4,
210
        .stepping = 3,
211
        .features = 0x008001BF,
212
        .xlevel = 0,
213
    },
214
    {
215
        .name = "pentium2",
216
        .family = 6,
217
        .model = 5,
218
        .stepping = 2,
219
        .features = 0x0183F9FF,
220
        .xlevel = 0,
221
    },
222
    {
223
        .name = "pentium3",
224
        .family = 6,
225
        .model = 7,
226
        .stepping = 3,
227
        .features = 0x0383F9FF,
228
        .xlevel = 0,
229
    },
230
};
231

  
232
int x86_find_cpu_by_name(const unsigned char *cpu_model)
233
{
234
    int ret;
235
    unsigned int i;
236

  
237
    char *s = strdup(cpu_model);
238
    char *featurestr, *name = strtok(s, ",");
239
    uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0;
240
    uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0;
241
    int family = -1, model = -1, stepping = -1;
242

  
243
    ret = -1;
244
    x86_cpu_def = NULL;
245
    for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++) {
246
        if (strcmp(name, x86_defs[i].name) == 0) {
247
            x86_cpu_def = &x86_defs[i];
248
            ret = 0;
249
            break;
250
        }
143 251
    }
144
    cpu_reset(env);
145
#ifdef USE_KQEMU
146
    kqemu_init(env);
147
#endif
148
    return env;
252
    if (!x86_cpu_def)
253
        goto error;
254

  
255
    featurestr = strtok(NULL, ",");
256

  
257
    while (featurestr) {
258
        char *val;
259
        if (featurestr[0] == '+') {
260
            add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features);
261
        } else if (featurestr[0] == '-') {
262
            add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features);
263
        } else if ((val = strchr(featurestr, '='))) {
264
            *val = 0; val++;
265
            if (!strcmp(featurestr, "family")) {
266
                char *err;
267
                family = strtol(val, &err, 10);
268
                if (!*val || *err || family < 0) {
269
                    fprintf(stderr, "bad numerical value %s\n", val);
270
                    x86_cpu_def = 0;
271
                    goto error;
272
                }
273
                x86_cpu_def->family = family;
274
            } else if (!strcmp(featurestr, "model")) {
275
                char *err;
276
                model = strtol(val, &err, 10);
277
                if (!*val || *err || model < 0 || model > 0xf) {
278
                    fprintf(stderr, "bad numerical value %s\n", val);
279
                    x86_cpu_def = 0;
280
                    goto error;
281
                }
282
                x86_cpu_def->model = model;
283
            } else if (!strcmp(featurestr, "stepping")) {
284
                char *err;
285
                stepping = strtol(val, &err, 10);
286
                if (!*val || *err || stepping < 0 || stepping > 0xf) {
287
                    fprintf(stderr, "bad numerical value %s\n", val);
288
                    x86_cpu_def = 0;
289
                    goto error;
290
                }
291
                x86_cpu_def->stepping = stepping;
292
            } else {
293
                fprintf(stderr, "unregnized feature %s\n", featurestr);
294
                x86_cpu_def = 0;
295
                goto error;
296
            }
297
        } else {
298
            fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
299
            x86_cpu_def = 0;
300
            goto error;
301
        }
302
        featurestr = strtok(NULL, ",");
303
    }
304
    x86_cpu_def->features |= plus_features;
305
    x86_cpu_def->ext_features |= plus_ext_features;
306
    x86_cpu_def->ext2_features |= plus_ext2_features;
307
    x86_cpu_def->ext3_features |= plus_ext3_features;
308
    x86_cpu_def->features &= ~minus_features;
309
    x86_cpu_def->ext_features &= ~minus_ext_features;
310
    x86_cpu_def->ext2_features &= ~minus_ext2_features;
311
    x86_cpu_def->ext3_features &= ~minus_ext3_features;
312

  
313
error:
314
    free(s);
315
    return ret;
316
}
317

  
318
void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
319
{
320
    unsigned int i;
321

  
322
    for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++)
323
        (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
324
}
325

  
326
int cpu_x86_register (CPUX86State *env, const x86_def_t *def)
327
{
328
    if (def->vendor1) {
329
        env->cpuid_vendor1 = def->vendor1;
330
        env->cpuid_vendor2 = def->vendor2;
331
        env->cpuid_vendor3 = def->vendor3;
332
    } else {
333
        env->cpuid_vendor1 = 0x756e6547; /* "Genu" */
334
        env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
335
        env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
336
    }
337
    env->cpuid_level = 2;
338
    env->cpuid_version = (def->family << 8) | (def->model << 4) | def->stepping;
339
    env->cpuid_features = def->features;
340
    env->pat = 0x0007040600070406ULL;
341
    env->cpuid_ext_features = def->ext_features;
342
    env->cpuid_ext2_features = def->ext2_features;
343
    env->cpuid_xlevel = def->xlevel;
344
    env->cpuid_ext3_features = def->ext3_features;
345
    {
346
        const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION;
347
        int c, len, i;
348
        len = strlen(model_id);
349
        for(i = 0; i < 48; i++) {
350
            if (i >= len)
351
                c = '\0';
352
            else
353
                c = model_id[i];
354
            env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
355
        }
356
    }
357
    return 0;
149 358
}
150 359

  
151 360
/* NOTE: must be called outside the CPU execute loop */
......
185 394
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0);
186 395

  
187 396
    env->eip = 0xfff0;
188
    env->regs[R_EDX] = 0x600; /* indicate P6 processor */
397
    env->regs[R_EDX] = env->cpuid_version;
189 398

  
190 399
    env->eflags = 0x2;
191 400

  

Also available in: Unified diff