Revision a049de61

b/hw/pc.c
676 676
                     DisplayState *ds, const char **fd_filename, int snapshot,
677 677
                     const char *kernel_filename, const char *kernel_cmdline,
678 678
                     const char *initrd_filename,
679
                     int pci_enabled)
679
                     int pci_enabled, const char *cpu_model)
680 680
{
681 681
    char buf[1024];
682 682
    int ret, linux_boot, i;
......
692 692
    linux_boot = (kernel_filename != NULL);
693 693

  
694 694
    /* init CPUs */
695
    if (cpu_model == NULL) {
696
#ifdef TARGET_X86_64
697
        cpu_model = "qemu64";
698
#else
699
        cpu_model = "qemu32";
700
#endif
701
    }
702
    
703
    if (x86_find_cpu_by_name(cpu_model)) {
704
        fprintf(stderr, "Unable to find x86 CPU definition\n");
705
        exit(1);
706
    }
695 707
    for(i = 0; i < smp_cpus; i++) {
696 708
        env = cpu_init();
697 709
        if (i != 0)
......
960 972
    pc_init1(ram_size, vga_ram_size, boot_device,
961 973
             ds, fd_filename, snapshot,
962 974
             kernel_filename, kernel_cmdline,
963
             initrd_filename, 1);
975
             initrd_filename, 1, cpu_model);
964 976
}
965 977

  
966 978
static void pc_init_isa(int ram_size, int vga_ram_size, const char *boot_device,
......
974 986
    pc_init1(ram_size, vga_ram_size, boot_device,
975 987
             ds, fd_filename, snapshot,
976 988
             kernel_filename, kernel_cmdline,
977
             initrd_filename, 0);
989
             initrd_filename, 0, cpu_model);
978 990
}
979 991

  
980 992
QEMUMachine pc_machine = {
b/target-i386/cpu.h
274 274
#define CPUID_CMOV (1 << 15)
275 275
#define CPUID_PAT  (1 << 16)
276 276
#define CPUID_PSE36   (1 << 17)
277
#define CPUID_PN   (1 << 18)
277 278
#define CPUID_CLFLUSH (1 << 19)
278
/* ... */
279
#define CPUID_DTS (1 << 21)
280
#define CPUID_ACPI (1 << 22)
279 281
#define CPUID_MMX  (1 << 23)
280 282
#define CPUID_FXSR (1 << 24)
281 283
#define CPUID_SSE  (1 << 25)
282 284
#define CPUID_SSE2 (1 << 26)
285
#define CPUID_SS (1 << 27)
286
#define CPUID_HT (1 << 28)
287
#define CPUID_TM (1 << 29)
288
#define CPUID_IA64 (1 << 30)
289
#define CPUID_PBE (1 << 31)
283 290

  
284 291
#define CPUID_EXT_SSE3     (1 << 0)
285 292
#define CPUID_EXT_MONITOR  (1 << 3)
293
#define CPUID_EXT_DSCPL    (1 << 4)
294
#define CPUID_EXT_VMX      (1 << 5)
295
#define CPUID_EXT_SMX      (1 << 6)
296
#define CPUID_EXT_EST      (1 << 7)
297
#define CPUID_EXT_TM2      (1 << 8)
298
#define CPUID_EXT_SSSE3    (1 << 9)
299
#define CPUID_EXT_CID      (1 << 10)
286 300
#define CPUID_EXT_CX16     (1 << 13)
301
#define CPUID_EXT_XTPR     (1 << 14)
302
#define CPUID_EXT_DCA      (1 << 17)
303
#define CPUID_EXT_POPCNT   (1 << 22)
287 304

  
288 305
#define CPUID_EXT2_SYSCALL (1 << 11)
306
#define CPUID_EXT2_MP      (1 << 19)
289 307
#define CPUID_EXT2_NX      (1 << 20)
308
#define CPUID_EXT2_MMXEXT  (1 << 22)
290 309
#define CPUID_EXT2_FFXSR   (1 << 25)
310
#define CPUID_EXT2_PDPE1GB (1 << 26)
311
#define CPUID_EXT2_RDTSCP  (1 << 27)
291 312
#define CPUID_EXT2_LM      (1 << 29)
313
#define CPUID_EXT2_3DNOWEXT (1 << 30)
314
#define CPUID_EXT2_3DNOW   (1 << 31)
292 315

  
316
#define CPUID_EXT3_LAHF_LM (1 << 0)
317
#define CPUID_EXT3_CMP_LEG (1 << 1)
293 318
#define CPUID_EXT3_SVM     (1 << 2)
319
#define CPUID_EXT3_EXTAPIC (1 << 3)
320
#define CPUID_EXT3_CR8LEG  (1 << 4)
321
#define CPUID_EXT3_ABM     (1 << 5)
322
#define CPUID_EXT3_SSE4A   (1 << 6)
323
#define CPUID_EXT3_MISALIGNSSE (1 << 7)
324
#define CPUID_EXT3_3DNOWPREFETCH (1 << 8)
325
#define CPUID_EXT3_OSVW    (1 << 9)
326
#define CPUID_EXT3_IBS     (1 << 10)
294 327

  
295 328
#define EXCP00_DIVZ	0
296 329
#define EXCP01_SSTP	1
......
566 599
CPUX86State *cpu_x86_init(void);
567 600
int cpu_x86_exec(CPUX86State *s);
568 601
void cpu_x86_close(CPUX86State *s);
602
int x86_find_cpu_by_name (const unsigned char *name);
603
void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt,
604
                                                 ...));
569 605
int cpu_get_pic_interrupt(CPUX86State *s);
570 606
/* MSDOS compatibility mode FPU exception support */
571 607
void cpu_set_ferr(CPUX86State *s);
......
689 725
#define cpu_exec cpu_x86_exec
690 726
#define cpu_gen_code cpu_x86_gen_code
691 727
#define cpu_signal_handler cpu_x86_signal_handler
728
#define cpu_list x86_cpu_list
692 729

  
693 730
/* MMU modes definitions */
694 731
#define MMU_MODE0_SUFFIX _kernel
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