From patchwork Fri Dec 28 20:34:05 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [RFC,8/9] target-i386: CPU subclasses for predefined CPU models From: Eduardo Habkost X-Patchwork-Id: 208591 Message-Id: <1356726846-10637-9-git-send-email-ehabkost@redhat.com> To: qemu-devel@nongnu.org Cc: Igor Mammedov , =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 28 Dec 2012 18:34:05 -0200 This uses a separate base class (TYPE_X86_PREDEF_CPU) for all the predefined CPU models, because those classes will have a x86_def_t struct embedded into the class struct (while TYPE_X86_HOST_CPU, for example, doesn't have it). The code that was inside x86_cpu_create_from_name() is now inside the instance_init function for TYPE_X86_PREDEF_CPU. The qemu_get_version() hacks inside x86_cpudef_setup() were moved to the class_init functions of qemu64, qemu32, and athlon CPU models. Signed-off-by: Eduardo Habkost --- target-i386/cpu.c | 656 ++++++++++++++++++++++++++++++++++++++++-------------- target-i386/cpu.h | 2 - 2 files changed, 494 insertions(+), 164 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 2b6cc3b..fa7fab0 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -273,8 +273,6 @@ static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features, } typedef struct x86_def_t { - struct x86_def_t *next; - const char *name; uint32_t level; char vendor[CPUID_VENDOR_SZ + 1]; int family; @@ -335,18 +333,51 @@ typedef struct x86_def_t { #define CPU_CLASS_NAME(name) (name "-" TYPE_X86_CPU) +/* -cpu "host" */ #define TYPE_X86_HOST_CPU CPU_CLASS_NAME("host") -/* maintains list of cpu model definitions - */ -static x86_def_t *x86_defs = {NULL}; +/* Base class for predefined CPU models: */ +#define TYPE_X86_PREDEF_CPU TYPE_X86_CPU "-predefined" + +#define PREDEF_X86_CPU_CLASS(klass) \ + OBJECT_CLASS_CHECK(PredefX86CPUClass, (klass), TYPE_X86_PREDEF_CPU) +#define PREDEF_X86_CPU(obj) \ + OBJECT_CHECK(X86CPU, (obj), TYPE_X86_PREDEF_CPU) +#define PREDEF_X86_CPU_GET_CLASS(obj) \ + OBJECT_GET_CLASS(PredefX86CPUClass, (obj), TYPE_X86_PREDEF_CPU) -/* built-in cpu model definitions (deprecated) + +/** + * PredefX86CPUClass: + * + * A predefined x86 CPU model. */ -static x86_def_t builtin_x86_defs[] = { - { - .name = "qemu64", +typedef struct PredefX86CPUClass { + /*< private >*/ + X86CPUClass parent_class; + /*< public >*/ + + x86_def_t cpudef; +} PredefX86CPUClass; + + +static void x86_cpu_predef_initfn(Object *obj); + +static const TypeInfo predef_x86_cpu_type_info = { + .name = TYPE_X86_PREDEF_CPU, + .parent = TYPE_X86_CPU, + .instance_size = sizeof(X86CPU), + .instance_init = x86_cpu_predef_initfn, + .abstract = true, + .class_size = sizeof(PredefX86CPUClass), +}; + + +static void x86_cpu_class_init_qemu64(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 4, .vendor = CPUID_VENDOR_AMD, .family = 6, @@ -361,9 +392,24 @@ static x86_def_t builtin_x86_defs[] = { .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A, .xlevel = 0x8000000A, - }, - { - .name = "phenom", + }; + pstrcpy(cc->cpudef.model_id, sizeof(cc->cpudef.model_id), "QEMU Virtual CPU version "); + pstrcat(cc->cpudef.model_id, sizeof(cc->cpudef.model_id), qemu_get_version()); +} + +static const TypeInfo x86_cpu_qemu64_type_info = { + .name = CPU_CLASS_NAME("qemu64"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_qemu64, +}; + +static void x86_cpu_class_init_phenom(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 5, .vendor = CPUID_VENDOR_AMD, .family = 16, @@ -387,9 +433,22 @@ static x86_def_t builtin_x86_defs[] = { .svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV, .xlevel = 0x8000001A, .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor" - }, - { - .name = "core2duo", + }; +} + +static const TypeInfo x86_cpu_phenom_type_info = { + .name = CPU_CLASS_NAME("phenom"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_phenom, +}; + +static void x86_cpu_class_init_core2duo(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 10, .vendor = CPUID_VENDOR_INTEL, .family = 6, @@ -406,9 +465,22 @@ static x86_def_t builtin_x86_defs[] = { .ext3_features = CPUID_EXT3_LAHF_LM, .xlevel = 0x80000008, .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz", - }, - { - .name = "kvm64", + }; +} + +static const TypeInfo x86_cpu_core2duo_type_info = { + .name = CPU_CLASS_NAME("core2duo"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_core2duo, +}; + +static void x86_cpu_class_init_kvm64(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 5, .vendor = CPUID_VENDOR_INTEL, .family = 15, @@ -430,9 +502,22 @@ static x86_def_t builtin_x86_defs[] = { .ext3_features = 0, .xlevel = 0x80000008, .model_id = "Common KVM processor" - }, - { - .name = "qemu32", + }; +} + +static const TypeInfo x86_cpu_kvm64_type_info = { + .name = CPU_CLASS_NAME("kvm64"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_kvm64, +}; + +static void x86_cpu_class_init_qemu32(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 4, .vendor = CPUID_VENDOR_INTEL, .family = 6, @@ -441,9 +526,24 @@ static x86_def_t builtin_x86_defs[] = { .features = PPRO_FEATURES, .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT, .xlevel = 0x80000004, - }, - { - .name = "kvm32", + }; + pstrcpy(cc->cpudef.model_id, sizeof(cc->cpudef.model_id), "QEMU Virtual CPU version "); + pstrcat(cc->cpudef.model_id, sizeof(cc->cpudef.model_id), qemu_get_version()); +} + +static const TypeInfo x86_cpu_qemu32_type_info = { + .name = CPU_CLASS_NAME("qemu32"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_qemu32, +}; + +static void x86_cpu_class_init_kvm32(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 5, .vendor = CPUID_VENDOR_INTEL, .family = 15, @@ -456,9 +556,22 @@ static x86_def_t builtin_x86_defs[] = { .ext3_features = 0, .xlevel = 0x80000008, .model_id = "Common 32-bit KVM processor" - }, - { - .name = "coreduo", + }; +} + +static const TypeInfo x86_cpu_kvm32_type_info = { + .name = CPU_CLASS_NAME("kvm32"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_kvm32, +}; + +static void x86_cpu_class_init_coreduo(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 10, .vendor = CPUID_VENDOR_INTEL, .family = 6, @@ -472,9 +585,22 @@ static x86_def_t builtin_x86_defs[] = { .ext2_features = CPUID_EXT2_NX, .xlevel = 0x80000008, .model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz", - }, - { - .name = "486", + }; +} + +static const TypeInfo x86_cpu_coreduo_type_info = { + .name = CPU_CLASS_NAME("coreduo"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_coreduo, +}; + +static void x86_cpu_class_init_486(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 1, .vendor = CPUID_VENDOR_INTEL, .family = 4, @@ -482,9 +608,22 @@ static x86_def_t builtin_x86_defs[] = { .stepping = 0, .features = I486_FEATURES, .xlevel = 0, - }, - { - .name = "pentium", + }; +} + +static const TypeInfo x86_cpu_486_type_info = { + .name = CPU_CLASS_NAME("486"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_486, +}; + +static void x86_cpu_class_init_pentium(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 1, .vendor = CPUID_VENDOR_INTEL, .family = 5, @@ -492,9 +631,22 @@ static x86_def_t builtin_x86_defs[] = { .stepping = 3, .features = PENTIUM_FEATURES, .xlevel = 0, - }, - { - .name = "pentium2", + }; +} + +static const TypeInfo x86_cpu_pentium_type_info = { + .name = CPU_CLASS_NAME("pentium"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_pentium, +}; + +static void x86_cpu_class_init_pentium2(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 2, .vendor = CPUID_VENDOR_INTEL, .family = 6, @@ -502,9 +654,22 @@ static x86_def_t builtin_x86_defs[] = { .stepping = 2, .features = PENTIUM2_FEATURES, .xlevel = 0, - }, - { - .name = "pentium3", + }; +} + +static const TypeInfo x86_cpu_pentium2_type_info = { + .name = CPU_CLASS_NAME("pentium2"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_pentium2, +}; + +static void x86_cpu_class_init_pentium3(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 2, .vendor = CPUID_VENDOR_INTEL, .family = 6, @@ -512,9 +677,22 @@ static x86_def_t builtin_x86_defs[] = { .stepping = 3, .features = PENTIUM3_FEATURES, .xlevel = 0, - }, - { - .name = "athlon", + }; +} + +static const TypeInfo x86_cpu_pentium3_type_info = { + .name = CPU_CLASS_NAME("pentium3"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_pentium3, +}; + +static void x86_cpu_class_init_athlon(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 2, .vendor = CPUID_VENDOR_AMD, .family = 6, @@ -525,9 +703,24 @@ static x86_def_t builtin_x86_defs[] = { .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT, .xlevel = 0x80000008, - }, - { - .name = "n270", + }; + pstrcpy(cc->cpudef.model_id, sizeof(cc->cpudef.model_id), "QEMU Virtual CPU version "); + pstrcat(cc->cpudef.model_id, sizeof(cc->cpudef.model_id), qemu_get_version()); +} + +static const TypeInfo x86_cpu_athlon_type_info = { + .name = CPU_CLASS_NAME("athlon"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_athlon, +}; + +static void x86_cpu_class_init_n270(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { /* original is on level 10 */ .level = 5, .vendor = CPUID_VENDOR_INTEL, @@ -545,9 +738,22 @@ static x86_def_t builtin_x86_defs[] = { .ext3_features = CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz", - }, - { - .name = "Conroe", + }; +} + +static const TypeInfo x86_cpu_n270_type_info = { + .name = CPU_CLASS_NAME("n270"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_n270, +}; + +static void x86_cpu_class_init_Conroe(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 2, .vendor = CPUID_VENDOR_INTEL, .family = 6, @@ -563,9 +769,22 @@ static x86_def_t builtin_x86_defs[] = { .ext3_features = CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)", - }, - { - .name = "Penryn", + }; +} + +static const TypeInfo x86_cpu_Conroe_type_info = { + .name = CPU_CLASS_NAME("Conroe"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_Conroe, +}; + +static void x86_cpu_class_init_Penryn(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 2, .vendor = CPUID_VENDOR_INTEL, .family = 6, @@ -582,9 +801,22 @@ static x86_def_t builtin_x86_defs[] = { .ext3_features = CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)", - }, - { - .name = "Nehalem", + }; +} + +static const TypeInfo x86_cpu_Penryn_type_info = { + .name = CPU_CLASS_NAME("Penryn"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_Penryn, +}; + +static void x86_cpu_class_init_Nehalem(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 2, .vendor = CPUID_VENDOR_INTEL, .family = 6, @@ -601,9 +833,22 @@ static x86_def_t builtin_x86_defs[] = { .ext3_features = CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)", - }, - { - .name = "Westmere", + }; +} + +static const TypeInfo x86_cpu_Nehalem_type_info = { + .name = CPU_CLASS_NAME("Nehalem"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_Nehalem, +}; + +static void x86_cpu_class_init_Westmere(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 11, .vendor = CPUID_VENDOR_INTEL, .family = 6, @@ -621,9 +866,22 @@ static x86_def_t builtin_x86_defs[] = { .ext3_features = CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)", - }, - { - .name = "SandyBridge", + }; +} + +static const TypeInfo x86_cpu_Westmere_type_info = { + .name = CPU_CLASS_NAME("Westmere"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_Westmere, +}; + +static void x86_cpu_class_init_SandyBridge(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 0xd, .vendor = CPUID_VENDOR_INTEL, .family = 6, @@ -644,9 +902,22 @@ static x86_def_t builtin_x86_defs[] = { .ext3_features = CPUID_EXT3_LAHF_LM, .xlevel = 0x8000000A, .model_id = "Intel Xeon E312xx (Sandy Bridge)", - }, - { - .name = "Haswell", + }; +} + +static const TypeInfo x86_cpu_SandyBridge_type_info = { + .name = CPU_CLASS_NAME("SandyBridge"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_SandyBridge, +}; + +static void x86_cpu_class_init_Haswell(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 0xd, .vendor = CPUID_VENDOR_INTEL, .family = 6, @@ -672,9 +943,22 @@ static x86_def_t builtin_x86_defs[] = { CPUID_7_0_EBX_RTM, .xlevel = 0x8000000A, .model_id = "Intel Core Processor (Haswell)", - }, - { - .name = "Opteron_G1", + }; +} + +static const TypeInfo x86_cpu_Haswell_type_info = { + .name = CPU_CLASS_NAME("Haswell"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_Haswell, +}; + +static void x86_cpu_class_init_Opteron_G1(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 5, .vendor = CPUID_VENDOR_AMD, .family = 15, @@ -694,9 +978,22 @@ static x86_def_t builtin_x86_defs[] = { CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU, .xlevel = 0x80000008, .model_id = "AMD Opteron 240 (Gen 1 Class Opteron)", - }, - { - .name = "Opteron_G2", + }; +} + +static const TypeInfo x86_cpu_Opteron_G1_type_info = { + .name = CPU_CLASS_NAME("Opteron_G1"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_Opteron_G1, +}; + +static void x86_cpu_class_init_Opteron_G2(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 5, .vendor = CPUID_VENDOR_AMD, .family = 15, @@ -718,9 +1015,22 @@ static x86_def_t builtin_x86_defs[] = { .ext3_features = CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, .xlevel = 0x80000008, .model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)", - }, - { - .name = "Opteron_G3", + }; +} + +static const TypeInfo x86_cpu_Opteron_G2_type_info = { + .name = CPU_CLASS_NAME("Opteron_G2"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_Opteron_G2, +}; + +static void x86_cpu_class_init_Opteron_G3(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 5, .vendor = CPUID_VENDOR_AMD, .family = 15, @@ -744,9 +1054,22 @@ static x86_def_t builtin_x86_defs[] = { CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, .xlevel = 0x80000008, .model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)", - }, - { - .name = "Opteron_G4", + }; +} + +static const TypeInfo x86_cpu_Opteron_G3_type_info = { + .name = CPU_CLASS_NAME("Opteron_G3"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_Opteron_G3, +}; + +static void x86_cpu_class_init_Opteron_G4(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 0xd, .vendor = CPUID_VENDOR_AMD, .family = 21, @@ -774,9 +1097,22 @@ static x86_def_t builtin_x86_defs[] = { CPUID_EXT3_LAHF_LM, .xlevel = 0x8000001A, .model_id = "AMD Opteron 62xx class CPU", - }, - { - .name = "Opteron_G5", + }; +} + +static const TypeInfo x86_cpu_Opteron_G4_type_info = { + .name = CPU_CLASS_NAME("Opteron_G4"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_Opteron_G4, +}; + +static void x86_cpu_class_init_Opteron_G5(ObjectClass *oc, void *data) +{ + PredefX86CPUClass *cc = PREDEF_X86_CPU_CLASS(oc); + cc->cpudef = (x86_def_t) { .level = 0xd, .vendor = CPUID_VENDOR_AMD, .family = 21, @@ -804,7 +1140,16 @@ static x86_def_t builtin_x86_defs[] = { CPUID_EXT3_LAHF_LM, .xlevel = 0x8000001A, .model_id = "AMD Opteron 63xx class CPU", - }, + }; +} + +static const TypeInfo x86_cpu_Opteron_G5_type_info = { + .name = CPU_CLASS_NAME("Opteron_G5"), + .parent = TYPE_X86_PREDEF_CPU, + .instance_size = sizeof(X86CPU), + .abstract = false, + .class_size = sizeof(PredefX86CPUClass), + .class_init = x86_cpu_class_init_Opteron_G5, }; static void x86cpu_vendor_words2str(char *dst, uint32_t ebx, uint32_t ecx, @@ -847,7 +1192,6 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) assert(kvm_enabled()); - x86_cpu_def->name = "host"; host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); x86cpu_vendor_words2str(x86_cpu_def->vendor, ebx, edx, ecx); @@ -1219,60 +1563,67 @@ static void cpudef_2_x86_cpu(X86CPU *cpu, x86_def_t *def, Error **errp) object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp); } +static void x86_cpu_predef_initfn(Object *obj) +{ + X86CPU *cpu = X86_CPU(obj); + PredefX86CPUClass *cc = PREDEF_X86_CPU_GET_CLASS(cpu); + Error *error = NULL; + x86_def_t cpudef; + + memcpy(&cpudef, &cc->cpudef, sizeof(cpudef)); + /* sysenter isn't supported on compatibility mode on AMD, syscall + * isn't supported in compatibility mode on Intel. + * Normally we advertise the actual cpu vendor, but you can override + * this using the 'vendor' property if you want to use KVM's + * sysenter/syscall emulation in compatibility mode and when doing + * cross vendor migration + */ + if (kvm_enabled()) { + uint32_t ebx = 0, ecx = 0, edx = 0; + host_cpuid(0, 0, NULL, &ebx, &ecx, &edx); + x86cpu_vendor_words2str(cpudef.vendor, ebx, edx, ecx); + } + + cpudef.kvm_features |= kvm_default_features; + add_flagname_to_bitmaps("hypervisor", &cpudef.features, + &cpudef.ext_features, + &cpudef.ext2_features, + &cpudef.ext3_features, + &cpudef.kvm_features, + &cpudef.svm_features, + &cpudef.cpuid_7_0_ebx_features); + + cpudef_2_x86_cpu(cpu, &cpudef, &error); + + if (error) { + error_report("cpu_init: %s", error_get_pretty(error)); + exit(1); + } +} + static X86CPU *x86_cpu_create_from_name(const char *name, Error **errp) { Error *error = NULL; X86CPU *cpu = NULL; - x86_def_t def1, *x86_cpu_def = &def1; + char *class_name = g_strdup_printf(CPU_CLASS_NAME("%s"), name); - memset(&def1, 0, sizeof(def1)); if (kvm_enabled() && name && strcmp(name, "host") == 0) { #ifdef CONFIG_KVM cpu = X86_CPU(object_new(TYPE_X86_HOST_CPU)); #endif } else { - x86_def_t *def; - - for (def = x86_defs; def; def = def->next) { - if (name && !strcmp(name, def->name)) { - break; - } - } - if (!def) { + if (!object_class_by_name(class_name)) { error_setg(&error, "Unable to find CPU definition: %s", name); goto out; } - cpu = X86_CPU(object_new(TYPE_X86_CPU)); - memcpy(x86_cpu_def, def, sizeof(*def)); - /* sysenter isn't supported on compatibility mode on AMD, syscall - * isn't supported in compatibility mode on Intel. - * Normally we advertise the actual cpu vendor, but you can override - * this using the 'vendor' property if you want to use KVM's - * sysenter/syscall emulation in compatibility mode and when doing - * cross vendor migration - */ - if (kvm_enabled()) { - uint32_t ebx = 0, ecx = 0, edx = 0; - host_cpuid(0, 0, NULL, &ebx, &ecx, &edx); - x86cpu_vendor_words2str(x86_cpu_def->vendor, ebx, edx, ecx); - } - - x86_cpu_def->kvm_features |= kvm_default_features; - add_flagname_to_bitmaps("hypervisor", &x86_cpu_def->features, - &x86_cpu_def->ext_features, - &x86_cpu_def->ext2_features, - &x86_cpu_def->ext3_features, - &x86_cpu_def->kvm_features, - &x86_cpu_def->svm_features, - &x86_cpu_def->cpuid_7_0_ebx_features); - - cpudef_2_x86_cpu(cpu, x86_cpu_def, &error); + cpu = X86_CPU(object_new(class_name)); } out: + g_free(class_name); if (error) { error_propagate(errp, error); if (cpu) { @@ -1452,13 +1803,9 @@ static void listflags(char *buf, int bufsize, uint32_t fbits, /* generate CPU information. */ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) { - x86_def_t *def; char buf[256]; - for (def = x86_defs; def; def = def->next) { - snprintf(buf, sizeof(buf), "%s", def->name); - (*cpu_fprintf)(f, "x86 %16s %-48s\n", buf, def->model_id); - } + /***** TODO: class listing */ if (kvm_enabled()) { (*cpu_fprintf)(f, "x86 %16s\n", "[host]"); } @@ -1476,20 +1823,7 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) { CpuDefinitionInfoList *cpu_list = NULL; - x86_def_t *def; - - for (def = x86_defs; def; def = def->next) { - CpuDefinitionInfoList *entry; - CpuDefinitionInfo *info; - - info = g_malloc0(sizeof(*info)); - info->name = g_strdup(def->name); - - entry = g_malloc0(sizeof(*entry)); - entry->value = info; - entry->next = cpu_list; - cpu_list = entry; - } + /***** TODO: class listing */ return cpu_list; } @@ -1577,33 +1911,6 @@ void cpu_clear_apic_feature(CPUX86State *env) #endif /* !CONFIG_USER_ONLY */ -/* Initialize list of CPU models, filling some non-static fields if necessary - */ -void x86_cpudef_setup(void) -{ - int i, j; - static const char *model_with_versions[] = { "qemu32", "qemu64", "athlon" }; - - for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) { - x86_def_t *def = &builtin_x86_defs[i]; - def->next = x86_defs; - - /* Look for specific "cpudef" models that */ - /* have the QEMU version in .model_id */ - for (j = 0; j < ARRAY_SIZE(model_with_versions); j++) { - if (strcmp(model_with_versions[j], def->name) == 0) { - pstrcpy(def->model_id, sizeof(def->model_id), - "QEMU Virtual CPU version "); - pstrcat(def->model_id, sizeof(def->model_id), - qemu_get_version()); - break; - } - } - - x86_defs = def; - } -} - static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { @@ -2169,7 +2476,7 @@ static const TypeInfo x86_cpu_type_info = { .parent = TYPE_CPU, .instance_size = sizeof(X86CPU), .instance_init = x86_cpu_initfn, - .abstract = false, + .abstract = true, .class_size = sizeof(X86CPUClass), .class_init = x86_cpu_common_class_init, }; @@ -2210,6 +2517,31 @@ static void x86_cpu_register_types(void) #ifdef CONFIG_KVM type_register_static(&x86_host_cpu_type_info); #endif + type_register_static(&predef_x86_cpu_type_info); + type_register_static(&x86_cpu_qemu64_type_info); + type_register_static(&x86_cpu_phenom_type_info); + type_register_static(&x86_cpu_core2duo_type_info); + type_register_static(&x86_cpu_kvm64_type_info); + type_register_static(&x86_cpu_qemu32_type_info); + type_register_static(&x86_cpu_kvm32_type_info); + type_register_static(&x86_cpu_coreduo_type_info); + type_register_static(&x86_cpu_486_type_info); + type_register_static(&x86_cpu_pentium_type_info); + type_register_static(&x86_cpu_pentium2_type_info); + type_register_static(&x86_cpu_pentium3_type_info); + type_register_static(&x86_cpu_athlon_type_info); + type_register_static(&x86_cpu_n270_type_info); + type_register_static(&x86_cpu_Conroe_type_info); + type_register_static(&x86_cpu_Penryn_type_info); + type_register_static(&x86_cpu_Nehalem_type_info); + type_register_static(&x86_cpu_Westmere_type_info); + type_register_static(&x86_cpu_SandyBridge_type_info); + type_register_static(&x86_cpu_Haswell_type_info); + type_register_static(&x86_cpu_Opteron_G1_type_info); + type_register_static(&x86_cpu_Opteron_G2_type_info); + type_register_static(&x86_cpu_Opteron_G3_type_info); + type_register_static(&x86_cpu_Opteron_G4_type_info); + type_register_static(&x86_cpu_Opteron_G5_type_info); } type_init(x86_cpu_register_types) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 2b45c09..6c41500 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -864,7 +864,6 @@ typedef struct CPUX86State { X86CPU *cpu_x86_init(const char *cpu_model); int cpu_x86_exec(CPUX86State *s); void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf); -void x86_cpudef_setup(void); int cpu_x86_support_mca_broadcast(CPUX86State *env); int cpu_get_pic_interrupt(CPUX86State *s); @@ -1046,7 +1045,6 @@ static inline CPUX86State *cpu_init(const char *cpu_model) #define cpu_gen_code cpu_x86_gen_code #define cpu_signal_handler cpu_x86_signal_handler #define cpu_list x86_cpu_list -#define cpudef_setup x86_cpudef_setup #define CPU_SAVE_VERSION 12