Revision b5ec5ce0 target-i386/helper.c

b/target-i386/helper.c
29 29
#include "kvm.h"
30 30

  
31 31
//#define DEBUG_MMU
32
#include "qemu-option.h"
33
#include "qemu-config.h"
32 34

  
33 35
/* feature flags taken from "Intel Processor Identification and the CPUID
34
 * Instruction" and AMD's "CPUID Specification". In cases of disagreement
35
 * about feature names, the Linux name is used. */
36
 * Instruction" and AMD's "CPUID Specification".  In cases of disagreement
37
 * between feature naming conventions, aliases may be added.
38
 */
36 39
static const char *feature_name[] = {
37
    "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
38
    "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
39
    "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, NULL, "ds" /* Intel dts */, "acpi", "mmx",
40
    "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe",
40
    "fpu", "vme", "de", "pse",
41
    "tsc", "msr", "pae", "mce",
42
    "cx8", "apic", NULL, "sep",
43
    "mtrr", "pge", "mca", "cmov",
44
    "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */,
45
    NULL, "ds" /* Intel dts */, "acpi", "mmx",
46
    "fxsr", "sse", "sse2", "ss",
47
    "ht" /* Intel htt */, "tm", "ia64", "pbe",
41 48
};
42 49
static const char *ext_feature_name[] = {
43
    "pni" /* Intel,AMD sse3 */, NULL, NULL, "monitor", "ds_cpl", "vmx", NULL /* Linux smx */, "est",
44
    "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
45
    NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
46
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, "hypervisor",
50
    "pni|sse3" /* Intel,AMD sse3 */, NULL, NULL, "monitor",
51
    "ds_cpl", "vmx", NULL /* Linux smx */, "est",
52
    "tm2", "ssse3", "cid", NULL,
53
    NULL, "cx16", "xtpr", NULL,
54
    NULL, NULL, "dca", "sse4.1|sse4_1",
55
    "sse4.2|sse4_2", "x2apic", NULL, "popcnt",
56
    NULL, NULL, NULL, NULL,
57
    NULL, NULL, NULL, "hypervisor",
47 58
};
48 59
static const char *ext2_feature_name[] = {
49
    "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
50
    "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", "mtrr", "pge", "mca", "cmov",
51
    "pat", "pse36", NULL, NULL /* Linux mp */, "nx" /* Intel xd */, NULL, "mmxext", "mmx",
52
    "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
60
    "fpu", "vme", "de", "pse",
61
    "tsc", "msr", "pae", "mce",
62
    "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall",
63
    "mtrr", "pge", "mca", "cmov",
64
    "pat", "pse36", NULL, NULL /* Linux mp */,
65
    "nx" /* Intel xd */, NULL, "mmxext", "mmx",
66
    "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp",
67
    NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
53 68
};
54 69
static const char *ext3_feature_name[] = {
55
    "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
56
    "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL,
57
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
58
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
70
    "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */,
71
    "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
72
    "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL,
73
    "skinit", "wdt", NULL, NULL,
74
    NULL, NULL, NULL, NULL,
75
    NULL, NULL, NULL, NULL,
76
    NULL, NULL, NULL, NULL,
77
    NULL, NULL, NULL, NULL,
59 78
};
60 79

  
61 80
static const char *kvm_feature_name[] = {
......
65 84
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
66 85
};
67 86

  
87
/* collects per-function cpuid data
88
 */
89
typedef struct model_features_t {
90
    uint32_t *guest_feat;
91
    uint32_t *host_feat;
92
    uint32_t check_feat;
93
    const char **flag_names;
94
    uint32_t cpuid;
95
    } model_features_t;
96

  
97
int check_cpuid = 0;
98
int enforce_cpuid = 0;
99

  
100
static void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax,
101
                       uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
102

  
103
#define iswhite(c) ((c) && ((c) <= ' ' || '~' < (c)))
104

  
105
/* general substring compare of *[s1..e1) and *[s2..e2).  sx is start of
106
 * a substring.  ex if !NULL points to the first char after a substring,
107
 * otherwise the string is assumed to sized by a terminating nul.
108
 * Return lexical ordering of *s1:*s2.
109
 */
110
static int sstrcmp(const char *s1, const char *e1, const char *s2,
111
    const char *e2)
112
{
113
    for (;;) {
114
        if (!*s1 || !*s2 || *s1 != *s2)
115
            return (*s1 - *s2);
116
        ++s1, ++s2;
117
        if (s1 == e1 && s2 == e2)
118
            return (0);
119
        else if (s1 == e1)
120
            return (*s2);
121
        else if (s2 == e2)
122
            return (*s1);
123
    }
124
}
125

  
126
/* compare *[s..e) to *altstr.  *altstr may be a simple string or multiple
127
 * '|' delimited (possibly empty) strings in which case search for a match
128
 * within the alternatives proceeds left to right.  Return 0 for success,
129
 * non-zero otherwise.
130
 */
131
static int altcmp(const char *s, const char *e, const char *altstr)
132
{
133
    const char *p, *q;
134

  
135
    for (q = p = altstr; ; ) {
136
        while (*p && *p != '|')
137
            ++p;
138
        if ((q == p && !*s) || (q != p && !sstrcmp(s, e, q, p)))
139
            return (0);
140
        if (!*p)
141
            return (1);
142
        else
143
            q = ++p;
144
    }
145
}
146

  
147
/* search featureset for flag *[s..e), if found set corresponding bit in
148
 * *pval and return success, otherwise return zero
149
 */
150
static int lookup_feature(uint32_t *pval, const char *s, const char *e,
151
    const char **featureset)
152
{
153
    uint32_t mask;
154
    const char **ppc;
155

  
156
    for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc)
157
        if (*ppc && !altcmp(s, e, *ppc)) {
158
            *pval |= mask;
159
            break;
160
        }
161
    return (mask ? 1 : 0);
162
}
163

  
68 164
static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
69 165
                                    uint32_t *ext_features,
70 166
                                    uint32_t *ext2_features,
71 167
                                    uint32_t *ext3_features,
72 168
                                    uint32_t *kvm_features)
73 169
{
74
    int i;
75
    int found = 0;
76

  
77
    for ( i = 0 ; i < 32 ; i++ )
78
        if (feature_name[i] && !strcmp (flagname, feature_name[i])) {
79
            *features |= 1 << i;
80
            found = 1;
81
        }
82
    for ( i = 0 ; i < 32 ; i++ )
83
        if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) {
84
            *ext_features |= 1 << i;
85
            found = 1;
86
        }
87
    for ( i = 0 ; i < 32 ; i++ )
88
        if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) {
89
            *ext2_features |= 1 << i;
90
            found = 1;
91
        }
92
    for ( i = 0 ; i < 32 ; i++ )
93
        if (ext3_feature_name[i] && !strcmp (flagname, ext3_feature_name[i])) {
94
            *ext3_features |= 1 << i;
95
            found = 1;
96
        }
97
    for ( i = 0 ; i < 32 ; i++ )
98
        if (kvm_feature_name[i] && !strcmp (flagname, kvm_feature_name[i])) {
99
            *kvm_features |= 1 << i;
100
            found = 1;
101
        }
102

  
103
    if (!found) {
104
        fprintf(stderr, "CPU feature %s not found\n", flagname);
105
    }
170
    if (!lookup_feature(features, flagname, NULL, feature_name) &&
171
        !lookup_feature(ext_features, flagname, NULL, ext_feature_name) &&
172
        !lookup_feature(ext2_features, flagname, NULL, ext2_feature_name) &&
173
        !lookup_feature(ext3_features, flagname, NULL, ext3_feature_name) &&
174
        !lookup_feature(kvm_features, flagname, NULL, kvm_feature_name))
175
            fprintf(stderr, "CPU feature %s not found\n", flagname);
106 176
}
107 177

  
108 178
typedef struct x86_def_t {
179
    struct x86_def_t *next;
109 180
    const char *name;
110 181
    uint32_t level;
111 182
    uint32_t vendor1, vendor2, vendor3;
......
116 187
    uint32_t xlevel;
117 188
    char model_id[48];
118 189
    int vendor_override;
190
    uint32_t flags;
119 191
} x86_def_t;
120 192

  
121 193
#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
......
129 201
          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
130 202
          CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
131 203
          CPUID_PAE | CPUID_SEP | CPUID_APIC)
132
static x86_def_t x86_defs[] = {
204

  
205
/* maintains list of cpu model definitions
206
 */
207
static x86_def_t *x86_defs = {NULL};
208

  
209
/* built-in cpu model definitions (deprecated)
210
 */
211
static x86_def_t builtin_x86_defs[] = {
133 212
#ifdef TARGET_X86_64
134 213
    {
135 214
        .name = "qemu64",
......
334 413
    },
335 414
};
336 415

  
337
static void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax,
338
                               uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
339

  
340 416
static int cpu_x86_fill_model_id(char *str)
341 417
{
342 418
    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
......
382 458
    return 0;
383 459
}
384 460

  
461
static int unavailable_host_feature(struct model_features_t *f, uint32_t mask)
462
{
463
    int i;
464

  
465
    for (i = 0; i < 32; ++i)
466
        if (1 << i & mask) {
467
            fprintf(stderr, "warning: host cpuid %04x_%04x lacks requested"
468
                " flag '%s' [0x%08x]\n",
469
                f->cpuid >> 16, f->cpuid & 0xffff,
470
                f->flag_names[i] ? f->flag_names[i] : "[reserved]", mask);
471
            break;
472
        }
473
    return 0;
474
}
475

  
476
/* best effort attempt to inform user requested cpu flags aren't making
477
 * their way to the guest.  Note: ft[].check_feat ideally should be
478
 * specified via a guest_def field to suppress report of extraneous flags.
479
 */
480
static int check_features_against_host(x86_def_t *guest_def)
481
{
482
    x86_def_t host_def;
483
    uint32_t mask;
484
    int rv, i;
485
    struct model_features_t ft[] = {
486
        {&guest_def->features, &host_def.features,
487
            ~0, feature_name, 0x00000000},
488
        {&guest_def->ext_features, &host_def.ext_features,
489
            ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001},
490
        {&guest_def->ext2_features, &host_def.ext2_features,
491
            ~PPRO_FEATURES, ext2_feature_name, 0x80000000},
492
        {&guest_def->ext3_features, &host_def.ext3_features,
493
            ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}};
494

  
495
    cpu_x86_fill_host(&host_def);
496
    for (rv = 0, i = 0; i < sizeof (ft) / sizeof (ft[0]); ++i)
497
        for (mask = 1; mask; mask <<= 1)
498
            if (ft[i].check_feat & mask && *ft[i].guest_feat & mask &&
499
                !(*ft[i].host_feat & mask)) {
500
                    unavailable_host_feature(&ft[i], mask);
501
                    rv = 1;
502
                }
503
    return rv;
504
}
505

  
385 506
static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
386 507
{
387 508
    unsigned int i;
......
393 514
    uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0, minus_kvm_features = 0;
394 515
    uint32_t numvalue;
395 516

  
396
    def = NULL;
397
    for (i = 0; i < ARRAY_SIZE(x86_defs); i++) {
398
        if (strcmp(name, x86_defs[i].name) == 0) {
399
            def = &x86_defs[i];
517
    for (def = x86_defs; def; def = def->next)
518
        if (!strcmp(name, def->name))
400 519
            break;
401
        }
402
    }
403 520
    if (kvm_enabled() && strcmp(name, "host") == 0) {
404 521
        cpu_x86_fill_host(x86_cpu_def);
405 522
    } else if (!def) {
......
488 605
                fprintf(stderr, "unrecognized feature %s\n", featurestr);
489 606
                goto error;
490 607
            }
608
        } else if (!strcmp(featurestr, "check")) {
609
            check_cpuid = 1;
610
        } else if (!strcmp(featurestr, "enforce")) {
611
            check_cpuid = enforce_cpuid = 1;
491 612
        } else {
492 613
            fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
493 614
            goto error;
......
504 625
    x86_cpu_def->ext2_features &= ~minus_ext2_features;
505 626
    x86_cpu_def->ext3_features &= ~minus_ext3_features;
506 627
    x86_cpu_def->kvm_features &= ~minus_kvm_features;
628
    if (check_cpuid) {
629
        if (check_features_against_host(x86_cpu_def) && enforce_cpuid)
630
            goto error;
631
    }
507 632
    free(s);
508 633
    return 0;
509 634

  
......
512 637
    return -1;
513 638
}
514 639

  
515
void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
640
/* generate a composite string into buf of all cpuid names in featureset
641
 * selected by fbits.  indicate truncation at bufsize in the event of overflow.
642
 * if flags, suppress names undefined in featureset.
643
 */
644
static void listflags(char *buf, int bufsize, uint32_t fbits,
645
    const char **featureset, uint32_t flags)
516 646
{
517
    unsigned int i;
647
    const char **p = &featureset[31];
648
    char *q, *b, bit;
649
    int nc;
650

  
651
    b = 4 <= bufsize ? buf + (bufsize -= 3) - 1 : NULL;
652
    *buf = '\0';
653
    for (q = buf, bit = 31; fbits && bufsize; --p, fbits &= ~(1 << bit), --bit)
654
        if (fbits & 1 << bit && (*p || !flags)) {
655
            if (*p)
656
                nc = snprintf(q, bufsize, "%s%s", q == buf ? "" : " ", *p);
657
            else
658
                nc = snprintf(q, bufsize, "%s[%d]", q == buf ? "" : " ", bit);
659
            if (bufsize <= nc) {
660
                if (b)
661
                    sprintf(b, "...");
662
                return;
663
            }
664
            q += nc;
665
            bufsize -= nc;
666
        }
667
}
518 668

  
519
    for (i = 0; i < ARRAY_SIZE(x86_defs); i++)
520
        (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name);
669
/* generate CPU information:
670
 * -?        list model names
671
 * -?model   list model names/IDs
672
 * -?dump    output all model (x86_def_t) data
673
 * -?cpuid   list all recognized cpuid flag names
674
 */ 
675
void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
676
                  const char *optarg)
677
{
678
    unsigned char model = !strcmp("?model", optarg);
679
    unsigned char dump = !strcmp("?dump", optarg);
680
    unsigned char cpuid = !strcmp("?cpuid", optarg);
681
    x86_def_t *def;
682
    char buf[256];
683

  
684
    if (cpuid) {
685
        (*cpu_fprintf)(f, "Recognized CPUID flags:\n");
686
        listflags(buf, sizeof (buf), (uint32_t)~0, feature_name, 1);
687
        (*cpu_fprintf)(f, "  f_edx: %s\n", buf);
688
        listflags(buf, sizeof (buf), (uint32_t)~0, ext_feature_name, 1);
689
        (*cpu_fprintf)(f, "  f_ecx: %s\n", buf);
690
        listflags(buf, sizeof (buf), (uint32_t)~0, ext2_feature_name, 1);
691
        (*cpu_fprintf)(f, "  extf_edx: %s\n", buf);
692
        listflags(buf, sizeof (buf), (uint32_t)~0, ext3_feature_name, 1);
693
        (*cpu_fprintf)(f, "  extf_ecx: %s\n", buf);
694
        return;
695
    }
696
    for (def = x86_defs; def; def = def->next) {
697
        snprintf(buf, sizeof (buf), def->flags ? "[%s]": "%s", def->name);
698
        if (model || dump) {
699
            (*cpu_fprintf)(f, "x86 %16s  %-48s\n", buf, def->model_id);
700
        } else {
701
            (*cpu_fprintf)(f, "x86 %16s\n", buf);
702
        }
703
        if (dump) {
704
            memcpy(buf, &def->vendor1, sizeof (def->vendor1));
705
            memcpy(buf + 4, &def->vendor2, sizeof (def->vendor2));
706
            memcpy(buf + 8, &def->vendor3, sizeof (def->vendor3));
707
            buf[12] = '\0';
708
            (*cpu_fprintf)(f,
709
                "  family %d model %d stepping %d level %d xlevel 0x%x"
710
                " vendor \"%s\"\n",
711
                def->family, def->model, def->stepping, def->level,
712
                def->xlevel, buf);
713
            listflags(buf, sizeof (buf), def->features, feature_name, 0);
714
            (*cpu_fprintf)(f, "  feature_edx %08x (%s)\n", def->features,
715
                buf);
716
            listflags(buf, sizeof (buf), def->ext_features, ext_feature_name,
717
                0);
718
            (*cpu_fprintf)(f, "  feature_ecx %08x (%s)\n", def->ext_features,
719
                buf);
720
            listflags(buf, sizeof (buf), def->ext2_features, ext2_feature_name,
721
                0);
722
            (*cpu_fprintf)(f, "  extfeature_edx %08x (%s)\n",
723
                def->ext2_features, buf);
724
            listflags(buf, sizeof (buf), def->ext3_features, ext3_feature_name,
725
                0);
726
            (*cpu_fprintf)(f, "  extfeature_ecx %08x (%s)\n",
727
                def->ext3_features, buf);
728
            (*cpu_fprintf)(f, "\n");
729
        }
730
    }
521 731
}
522 732

  
523 733
static int cpu_x86_register (CPUX86State *env, const char *cpu_model)
......
566 776
    return 0;
567 777
}
568 778

  
779
#if !defined(CONFIG_LINUX_USER)
780
/* copy vendor id string to 32 bit register, nul pad as needed
781
 */
782
static void cpyid(const char *s, uint32_t *id)
783
{
784
    char *d = (char *)id;
785
    char i;
786

  
787
    for (i = sizeof (*id); i--; )
788
        *d++ = *s ? *s++ : '\0';
789
}
790

  
791
/* interpret radix and convert from string to arbitrary scalar,
792
 * otherwise flag failure
793
 */
794
#define setscalar(pval, str, perr)                      \
795
{                                                       \
796
    char *pend;                                         \
797
    unsigned long ul;                                   \
798
                                                        \
799
    ul = strtoul(str, &pend, 0);                        \
800
    *str && !*pend ? (*pval = ul) : (*perr = 1);        \
801
}
802

  
803
/* map cpuid options to feature bits, otherwise return failure
804
 * (option tags in *str are delimited by whitespace)
805
 */
806
static void setfeatures(uint32_t *pval, const char *str,
807
    const char **featureset, int *perr)
808
{
809
    const char *p, *q;
810

  
811
    for (q = p = str; *p || *q; q = p) {
812
        while (iswhite(*p))
813
            q = ++p; 
814
        while (*p && !iswhite(*p))
815
            ++p;
816
        if (!*q && !*p)
817
            return;
818
        if (!lookup_feature(pval, q, p, featureset)) {
819
            fprintf(stderr, "error: feature \"%.*s\" not available in set\n",
820
                (int)(p - q), q);
821
            *perr = 1;
822
            return;
823
        }
824
    }
825
}
826

  
827
/* map config file options to x86_def_t form
828
 */
829
static int cpudef_setfield(const char *name, const char *str, void *opaque)
830
{
831
    x86_def_t *def = opaque;
832
    int err = 0;
833

  
834
    if (!strcmp(name, "name")) {
835
        def->name = strdup(str);
836
    } else if (!strcmp(name, "model_id")) {
837
        strncpy(def->model_id, str, sizeof (def->model_id));
838
    } else if (!strcmp(name, "level")) {
839
        setscalar(&def->level, str, &err)
840
    } else if (!strcmp(name, "vendor")) {
841
        cpyid(&str[0], &def->vendor1);
842
        cpyid(&str[4], &def->vendor2);
843
        cpyid(&str[8], &def->vendor3);
844
    } else if (!strcmp(name, "family")) {
845
        setscalar(&def->family, str, &err)
846
    } else if (!strcmp(name, "model")) {
847
        setscalar(&def->model, str, &err)
848
    } else if (!strcmp(name, "stepping")) {
849
        setscalar(&def->stepping, str, &err)
850
    } else if (!strcmp(name, "feature_edx")) {
851
        setfeatures(&def->features, str, feature_name, &err);
852
    } else if (!strcmp(name, "feature_ecx")) {
853
        setfeatures(&def->ext_features, str, ext_feature_name, &err);
854
    } else if (!strcmp(name, "extfeature_edx")) {
855
        setfeatures(&def->ext2_features, str, ext2_feature_name, &err);
856
    } else if (!strcmp(name, "extfeature_ecx")) {
857
        setfeatures(&def->ext3_features, str, ext3_feature_name, &err);
858
    } else if (!strcmp(name, "xlevel")) {
859
        setscalar(&def->xlevel, str, &err)
860
    } else {
861
        fprintf(stderr, "error: unknown option [%s = %s]\n", name, str);
862
        return (1);
863
    }
864
    if (err) {
865
        fprintf(stderr, "error: bad option value [%s = %s]\n", name, str);
866
        return (1);
867
    }
868
    return (0);
869
}
870

  
871
/* register config file entry as x86_def_t
872
 */
873
static int cpudef_register(QemuOpts *opts, void *opaque)
874
{
875
    x86_def_t *def = qemu_mallocz(sizeof (x86_def_t));
876

  
877
    qemu_opt_foreach(opts, cpudef_setfield, def, 1);
878
    def->next = x86_defs;
879
    x86_defs = def;
880
    return (0);
881
}
882
#endif	/* !CONFIG_LINUX_USER */
883

  
884
/* register "cpudef" models defined in configuration file.  Here we first
885
 * preload any built-in definitions
886
 */
887
void x86_cpudef_setup(void)
888
{
889
    int i;
890

  
891
    for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) {
892
        builtin_x86_defs[i].next = x86_defs;
893
        builtin_x86_defs[i].flags = 1;
894
        x86_defs = &builtin_x86_defs[i];
895
    }
896
#if !defined(CONFIG_LINUX_USER)
897
    qemu_opts_foreach(&qemu_cpudef_opts, cpudef_register, NULL, 0);
898
#endif
899
}
900

  
569 901
/* NOTE: must be called outside the CPU execute loop */
570 902
void cpu_reset(CPUX86State *env)
571 903
{

Also available in: Unified diff