16efef58eSEduardo Habkost #include "qemu/osdep.h" 26efef58eSEduardo Habkost #include "qemu-common.h" 36efef58eSEduardo Habkost #include "qapi/qmp/qdict.h" 447e6b297SMarkus Armbruster #include "qapi/qmp/qlist.h" 501b2ffceSMarc-André Lureau #include "qapi/qmp/qnum.h" 6a2f9976eSEduardo Habkost #include "qapi/qmp/qbool.h" 7dd210749SThomas Huth #include "libqtest-single.h" 86efef58eSEduardo Habkost 96efef58eSEduardo Habkost static char *get_cpu0_qom_path(void) 106efef58eSEduardo Habkost { 116efef58eSEduardo Habkost QDict *resp; 126efef58eSEduardo Habkost QList *ret; 136efef58eSEduardo Habkost QDict *cpu0; 146efef58eSEduardo Habkost char *path; 156efef58eSEduardo Habkost 168af54b91SDaniel P. Berrangé resp = qmp("{'execute': 'query-cpus-fast', 'arguments': {}}"); 176efef58eSEduardo Habkost g_assert(qdict_haskey(resp, "return")); 186efef58eSEduardo Habkost ret = qdict_get_qlist(resp, "return"); 196efef58eSEduardo Habkost 207dc847ebSMax Reitz cpu0 = qobject_to(QDict, qlist_peek(ret)); 218af54b91SDaniel P. Berrangé path = g_strdup(qdict_get_str(cpu0, "qom-path")); 22cb3e7f08SMarc-André Lureau qobject_unref(resp); 236efef58eSEduardo Habkost return path; 246efef58eSEduardo Habkost } 256efef58eSEduardo Habkost 266efef58eSEduardo Habkost static QObject *qom_get(const char *path, const char *prop) 276efef58eSEduardo Habkost { 286efef58eSEduardo Habkost QDict *resp = qmp("{ 'execute': 'qom-get'," 296efef58eSEduardo Habkost " 'arguments': { 'path': %s," 306efef58eSEduardo Habkost " 'property': %s } }", 316efef58eSEduardo Habkost path, prop); 326efef58eSEduardo Habkost QObject *ret = qdict_get(resp, "return"); 33cb3e7f08SMarc-André Lureau qobject_ref(ret); 34cb3e7f08SMarc-André Lureau qobject_unref(resp); 356efef58eSEduardo Habkost return ret; 366efef58eSEduardo Habkost } 376efef58eSEduardo Habkost 38a2f9976eSEduardo Habkost static bool qom_get_bool(const char *path, const char *prop) 39a2f9976eSEduardo Habkost { 407dc847ebSMax Reitz QBool *value = qobject_to(QBool, qom_get(path, prop)); 41a2f9976eSEduardo Habkost bool b = qbool_get_bool(value); 42a2f9976eSEduardo Habkost 43cb3e7f08SMarc-André Lureau qobject_unref(value); 44a2f9976eSEduardo Habkost return b; 45a2f9976eSEduardo Habkost } 46a2f9976eSEduardo Habkost 476efef58eSEduardo Habkost typedef struct CpuidTestArgs { 486efef58eSEduardo Habkost const char *cmdline; 496efef58eSEduardo Habkost const char *property; 506efef58eSEduardo Habkost int64_t expected_value; 516efef58eSEduardo Habkost } CpuidTestArgs; 526efef58eSEduardo Habkost 536efef58eSEduardo Habkost static void test_cpuid_prop(const void *data) 546efef58eSEduardo Habkost { 556efef58eSEduardo Habkost const CpuidTestArgs *args = data; 566efef58eSEduardo Habkost char *path; 5701b2ffceSMarc-André Lureau QNum *value; 5801b2ffceSMarc-André Lureau int64_t val; 596efef58eSEduardo Habkost 606efef58eSEduardo Habkost qtest_start(args->cmdline); 616efef58eSEduardo Habkost path = get_cpu0_qom_path(); 627dc847ebSMax Reitz value = qobject_to(QNum, qom_get(path, args->property)); 6301b2ffceSMarc-André Lureau g_assert(qnum_get_try_int(value, &val)); 6401b2ffceSMarc-André Lureau g_assert_cmpint(val, ==, args->expected_value); 656efef58eSEduardo Habkost qtest_end(); 666efef58eSEduardo Habkost 67cb3e7f08SMarc-André Lureau qobject_unref(value); 686efef58eSEduardo Habkost g_free(path); 696efef58eSEduardo Habkost } 706efef58eSEduardo Habkost 716efef58eSEduardo Habkost static void add_cpuid_test(const char *name, const char *cmdline, 726efef58eSEduardo Habkost const char *property, int64_t expected_value) 736efef58eSEduardo Habkost { 746efef58eSEduardo Habkost CpuidTestArgs *args = g_new0(CpuidTestArgs, 1); 756efef58eSEduardo Habkost args->cmdline = cmdline; 766efef58eSEduardo Habkost args->property = property; 776efef58eSEduardo Habkost args->expected_value = expected_value; 786efef58eSEduardo Habkost qtest_add_data_func(name, args, test_cpuid_prop); 796efef58eSEduardo Habkost } 806efef58eSEduardo Habkost 8117e8f541SEduardo Habkost 8217e8f541SEduardo Habkost /* Parameters to a add_feature_test() test case */ 8317e8f541SEduardo Habkost typedef struct FeatureTestArgs { 8417e8f541SEduardo Habkost /* cmdline to start QEMU */ 8517e8f541SEduardo Habkost const char *cmdline; 8617e8f541SEduardo Habkost /* 8717e8f541SEduardo Habkost * cpuid-input-eax and cpuid-input-ecx values to look for, 8817e8f541SEduardo Habkost * in "feature-words" and "filtered-features" properties. 8917e8f541SEduardo Habkost */ 9017e8f541SEduardo Habkost uint32_t in_eax, in_ecx; 9117e8f541SEduardo Habkost /* The register name to look for, in the X86CPUFeatureWordInfo array */ 9217e8f541SEduardo Habkost const char *reg; 9317e8f541SEduardo Habkost /* The bit to check in X86CPUFeatureWordInfo.features */ 9417e8f541SEduardo Habkost int bitnr; 9517e8f541SEduardo Habkost /* The expected value for the bit in (X86CPUFeatureWordInfo.features) */ 9617e8f541SEduardo Habkost bool expected_value; 9717e8f541SEduardo Habkost } FeatureTestArgs; 9817e8f541SEduardo Habkost 9917e8f541SEduardo Habkost /* Get the value for a feature word in a X86CPUFeatureWordInfo list */ 10017e8f541SEduardo Habkost static uint32_t get_feature_word(QList *features, uint32_t eax, uint32_t ecx, 10117e8f541SEduardo Habkost const char *reg) 10217e8f541SEduardo Habkost { 10317e8f541SEduardo Habkost const QListEntry *e; 10417e8f541SEduardo Habkost 10517e8f541SEduardo Habkost for (e = qlist_first(features); e; e = qlist_next(e)) { 1067dc847ebSMax Reitz QDict *w = qobject_to(QDict, qlist_entry_obj(e)); 10717e8f541SEduardo Habkost const char *rreg = qdict_get_str(w, "cpuid-register"); 10817e8f541SEduardo Habkost uint32_t reax = qdict_get_int(w, "cpuid-input-eax"); 10917e8f541SEduardo Habkost bool has_ecx = qdict_haskey(w, "cpuid-input-ecx"); 11017e8f541SEduardo Habkost uint32_t recx = 0; 11101b2ffceSMarc-André Lureau int64_t val; 11217e8f541SEduardo Habkost 11317e8f541SEduardo Habkost if (has_ecx) { 11417e8f541SEduardo Habkost recx = qdict_get_int(w, "cpuid-input-ecx"); 11517e8f541SEduardo Habkost } 11617e8f541SEduardo Habkost if (eax == reax && (!has_ecx || ecx == recx) && !strcmp(rreg, reg)) { 1177dc847ebSMax Reitz g_assert(qnum_get_try_int(qobject_to(QNum, 1187dc847ebSMax Reitz qdict_get(w, "features")), 11901b2ffceSMarc-André Lureau &val)); 12001b2ffceSMarc-André Lureau return val; 12117e8f541SEduardo Habkost } 12217e8f541SEduardo Habkost } 12317e8f541SEduardo Habkost return 0; 12417e8f541SEduardo Habkost } 12517e8f541SEduardo Habkost 12617e8f541SEduardo Habkost static void test_feature_flag(const void *data) 12717e8f541SEduardo Habkost { 12817e8f541SEduardo Habkost const FeatureTestArgs *args = data; 12917e8f541SEduardo Habkost char *path; 13017e8f541SEduardo Habkost QList *present, *filtered; 13117e8f541SEduardo Habkost uint32_t value; 13217e8f541SEduardo Habkost 13317e8f541SEduardo Habkost qtest_start(args->cmdline); 13417e8f541SEduardo Habkost path = get_cpu0_qom_path(); 1357dc847ebSMax Reitz present = qobject_to(QList, qom_get(path, "feature-words")); 1367dc847ebSMax Reitz filtered = qobject_to(QList, qom_get(path, "filtered-features")); 13717e8f541SEduardo Habkost value = get_feature_word(present, args->in_eax, args->in_ecx, args->reg); 13817e8f541SEduardo Habkost value |= get_feature_word(filtered, args->in_eax, args->in_ecx, args->reg); 13917e8f541SEduardo Habkost qtest_end(); 14017e8f541SEduardo Habkost 14117e8f541SEduardo Habkost g_assert(!!(value & (1U << args->bitnr)) == args->expected_value); 14217e8f541SEduardo Habkost 143cb3e7f08SMarc-André Lureau qobject_unref(present); 144cb3e7f08SMarc-André Lureau qobject_unref(filtered); 14517e8f541SEduardo Habkost g_free(path); 14617e8f541SEduardo Habkost } 14717e8f541SEduardo Habkost 14817e8f541SEduardo Habkost /* 14917e8f541SEduardo Habkost * Add test case to ensure that a given feature flag is set in 15017e8f541SEduardo Habkost * either "feature-words" or "filtered-features", when running QEMU 15117e8f541SEduardo Habkost * using cmdline 15217e8f541SEduardo Habkost */ 15317e8f541SEduardo Habkost static FeatureTestArgs *add_feature_test(const char *name, const char *cmdline, 15417e8f541SEduardo Habkost uint32_t eax, uint32_t ecx, 15517e8f541SEduardo Habkost const char *reg, int bitnr, 15617e8f541SEduardo Habkost bool expected_value) 15717e8f541SEduardo Habkost { 15817e8f541SEduardo Habkost FeatureTestArgs *args = g_new0(FeatureTestArgs, 1); 15917e8f541SEduardo Habkost args->cmdline = cmdline; 16017e8f541SEduardo Habkost args->in_eax = eax; 16117e8f541SEduardo Habkost args->in_ecx = ecx; 16217e8f541SEduardo Habkost args->reg = reg; 16317e8f541SEduardo Habkost args->bitnr = bitnr; 16417e8f541SEduardo Habkost args->expected_value = expected_value; 16517e8f541SEduardo Habkost qtest_add_data_func(name, args, test_feature_flag); 16617e8f541SEduardo Habkost return args; 16717e8f541SEduardo Habkost } 16817e8f541SEduardo Habkost 16983a00f60SEduardo Habkost static void test_plus_minus_subprocess(void) 170a2f9976eSEduardo Habkost { 171a2f9976eSEduardo Habkost char *path; 172a2f9976eSEduardo Habkost 173a2f9976eSEduardo Habkost /* Rules: 174a2f9976eSEduardo Habkost * 1)"-foo" overrides "+foo" 175a2f9976eSEduardo Habkost * 2) "[+-]foo" overrides "foo=..." 176a2f9976eSEduardo Habkost * 3) Old feature names with underscores (e.g. "sse4_2") 177a2f9976eSEduardo Habkost * should keep working 178a2f9976eSEduardo Habkost * 17983a00f60SEduardo Habkost * Note: rules 1 and 2 are planned to be removed soon, and 18083a00f60SEduardo Habkost * should generate a warning. 181a2f9976eSEduardo Habkost */ 182a2f9976eSEduardo Habkost qtest_start("-cpu pentium,-fpu,+fpu,-mce,mce=on,+cx8,cx8=off,+sse4_1,sse4_2=on"); 183a2f9976eSEduardo Habkost path = get_cpu0_qom_path(); 184a2f9976eSEduardo Habkost 185a2f9976eSEduardo Habkost g_assert_false(qom_get_bool(path, "fpu")); 186a2f9976eSEduardo Habkost g_assert_false(qom_get_bool(path, "mce")); 187a2f9976eSEduardo Habkost g_assert_true(qom_get_bool(path, "cx8")); 188a2f9976eSEduardo Habkost 189a2f9976eSEduardo Habkost /* Test both the original and the alias feature names: */ 190a2f9976eSEduardo Habkost g_assert_true(qom_get_bool(path, "sse4-1")); 191a2f9976eSEduardo Habkost g_assert_true(qom_get_bool(path, "sse4.1")); 192a2f9976eSEduardo Habkost 193a2f9976eSEduardo Habkost g_assert_true(qom_get_bool(path, "sse4-2")); 194a2f9976eSEduardo Habkost g_assert_true(qom_get_bool(path, "sse4.2")); 195a2f9976eSEduardo Habkost 196a2f9976eSEduardo Habkost qtest_end(); 197a2f9976eSEduardo Habkost g_free(path); 198a2f9976eSEduardo Habkost } 199a2f9976eSEduardo Habkost 20083a00f60SEduardo Habkost static void test_plus_minus(void) 20183a00f60SEduardo Habkost { 20283a00f60SEduardo Habkost g_test_trap_subprocess("/x86/cpuid/parsing-plus-minus/subprocess", 0, 0); 20383a00f60SEduardo Habkost g_test_trap_assert_passed(); 20483a00f60SEduardo Habkost g_test_trap_assert_stderr("*Ambiguous CPU model string. " 20583a00f60SEduardo Habkost "Don't mix both \"-mce\" and \"mce=on\"*"); 20683a00f60SEduardo Habkost g_test_trap_assert_stderr("*Ambiguous CPU model string. " 20783a00f60SEduardo Habkost "Don't mix both \"+cx8\" and \"cx8=off\"*"); 20883a00f60SEduardo Habkost g_test_trap_assert_stdout(""); 20983a00f60SEduardo Habkost } 21083a00f60SEduardo Habkost 2116efef58eSEduardo Habkost int main(int argc, char **argv) 2126efef58eSEduardo Habkost { 2136efef58eSEduardo Habkost g_test_init(&argc, &argv, NULL); 2146efef58eSEduardo Habkost 21583a00f60SEduardo Habkost g_test_add_func("/x86/cpuid/parsing-plus-minus/subprocess", 21683a00f60SEduardo Habkost test_plus_minus_subprocess); 21783a00f60SEduardo Habkost g_test_add_func("/x86/cpuid/parsing-plus-minus", test_plus_minus); 218a2f9976eSEduardo Habkost 2196efef58eSEduardo Habkost /* Original level values for CPU models: */ 2206efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/phenom/level", 2216efef58eSEduardo Habkost "-cpu phenom", "level", 5); 2226efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/Conroe/level", 2236efef58eSEduardo Habkost "-cpu Conroe", "level", 10); 2246efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/SandyBridge/level", 2256efef58eSEduardo Habkost "-cpu SandyBridge", "level", 0xd); 2266efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/486/xlevel", 2276efef58eSEduardo Habkost "-cpu 486", "xlevel", 0); 2286efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/core2duo/xlevel", 2296efef58eSEduardo Habkost "-cpu core2duo", "xlevel", 0x80000008); 2306efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/phenom/xlevel", 2316efef58eSEduardo Habkost "-cpu phenom", "xlevel", 0x8000001A); 2320c3d7c00SEduardo Habkost add_cpuid_test("x86/cpuid/athlon/xlevel", 2330c3d7c00SEduardo Habkost "-cpu athlon", "xlevel", 0x80000008); 2346efef58eSEduardo Habkost 2356efef58eSEduardo Habkost /* If level is not large enough, it should increase automatically: */ 236c39c0edfSEduardo Habkost /* CPUID[6].EAX: */ 237c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/phenom/arat", 238b7d77f5aSDaniel P. Berrangé "-cpu 486,arat=on", "level", 6); 2396efef58eSEduardo Habkost /* CPUID[EAX=7,ECX=0].EBX: */ 2406efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/phenom/fsgsbase", 241b7d77f5aSDaniel P. Berrangé "-cpu phenom,fsgsbase=on", "level", 7); 242c39c0edfSEduardo Habkost /* CPUID[EAX=7,ECX=0].ECX: */ 243c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/phenom/avx512vbmi", 244b7d77f5aSDaniel P. Berrangé "-cpu phenom,avx512vbmi=on", "level", 7); 245c39c0edfSEduardo Habkost /* CPUID[EAX=0xd,ECX=1].EAX: */ 246c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/phenom/xsaveopt", 247b7d77f5aSDaniel P. Berrangé "-cpu phenom,xsaveopt=on", "level", 0xd); 248c39c0edfSEduardo Habkost /* CPUID[8000_0001].EDX: */ 249c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/486/3dnow", 250b7d77f5aSDaniel P. Berrangé "-cpu 486,3dnow=on", "xlevel", 0x80000001); 251c39c0edfSEduardo Habkost /* CPUID[8000_0001].ECX: */ 252c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/486/sse4a", 253b7d77f5aSDaniel P. Berrangé "-cpu 486,sse4a=on", "xlevel", 0x80000001); 254c39c0edfSEduardo Habkost /* CPUID[8000_0007].EDX: */ 255c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/486/invtsc", 256b7d77f5aSDaniel P. Berrangé "-cpu 486,invtsc=on", "xlevel", 0x80000007); 257c39c0edfSEduardo Habkost /* CPUID[8000_000A].EDX: */ 258c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/486/npt", 259b7d77f5aSDaniel P. Berrangé "-cpu 486,svm=on,npt=on", "xlevel", 0x8000000A); 260c39c0edfSEduardo Habkost /* CPUID[C000_0001].EDX: */ 261c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel2/phenom/xstore", 262b7d77f5aSDaniel P. Berrangé "-cpu phenom,xstore=on", "xlevel2", 0xC0000001); 2630c3d7c00SEduardo Habkost /* SVM needs CPUID[0x8000000A] */ 2640c3d7c00SEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/athlon/svm", 265b7d77f5aSDaniel P. Berrangé "-cpu athlon,svm=on", "xlevel", 0x8000000A); 266c39c0edfSEduardo Habkost 2676efef58eSEduardo Habkost 2686efef58eSEduardo Habkost /* If level is already large enough, it shouldn't change: */ 2696efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/SandyBridge/multiple", 270b7d77f5aSDaniel P. Berrangé "-cpu SandyBridge,arat=on,fsgsbase=on,avx512vbmi=on", 2716efef58eSEduardo Habkost "level", 0xd); 272c39c0edfSEduardo Habkost /* If level is explicitly set, it shouldn't change: */ 273c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/486/fixed/0xF", 274b7d77f5aSDaniel P. Berrangé "-cpu 486,level=0xF,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", 275c39c0edfSEduardo Habkost "level", 0xF); 276c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/486/fixed/2", 277b7d77f5aSDaniel P. Berrangé "-cpu 486,level=2,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", 278c39c0edfSEduardo Habkost "level", 2); 279c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/486/fixed/0", 280b7d77f5aSDaniel P. Berrangé "-cpu 486,level=0,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", 281c39c0edfSEduardo Habkost "level", 0); 2826efef58eSEduardo Habkost 2836efef58eSEduardo Habkost /* if xlevel is already large enough, it shouldn't change: */ 2846efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/phenom/3dnow", 285b7d77f5aSDaniel P. Berrangé "-cpu phenom,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", 2866efef58eSEduardo Habkost "xlevel", 0x8000001A); 287c39c0edfSEduardo Habkost /* If xlevel is explicitly set, it shouldn't change: */ 288c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/80000002", 289b7d77f5aSDaniel P. Berrangé "-cpu 486,xlevel=0x80000002,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", 290c39c0edfSEduardo Habkost "xlevel", 0x80000002); 291c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/8000001A", 292b7d77f5aSDaniel P. Berrangé "-cpu 486,xlevel=0x8000001A,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", 293c39c0edfSEduardo Habkost "xlevel", 0x8000001A); 294c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/phenom/fixed/0", 295b7d77f5aSDaniel P. Berrangé "-cpu 486,xlevel=0,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", 296c39c0edfSEduardo Habkost "xlevel", 0); 2976efef58eSEduardo Habkost 2986efef58eSEduardo Habkost /* if xlevel2 is already large enough, it shouldn't change: */ 2996efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel2/486/fixed", 300b7d77f5aSDaniel P. Berrangé "-cpu 486,xlevel2=0xC0000002,xstore=on", 3016efef58eSEduardo Habkost "xlevel2", 0xC0000002); 3026efef58eSEduardo Habkost 303df3e9af8SEduardo Habkost /* Check compatibility of old machine-types that didn't 304df3e9af8SEduardo Habkost * auto-increase level/xlevel/xlevel2: */ 305*7539fa01SThomas Huth if (qtest_has_machine("pc-i440fx-2.7")) { 306df3e9af8SEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/pc-2.7", 307b7d77f5aSDaniel P. Berrangé "-machine pc-i440fx-2.7 -cpu 486,arat=on,avx512vbmi=on,xsaveopt=on", 308df3e9af8SEduardo Habkost "level", 1); 309df3e9af8SEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/pc-2.7", 310b7d77f5aSDaniel P. Berrangé "-machine pc-i440fx-2.7 -cpu 486,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", 311df3e9af8SEduardo Habkost "xlevel", 0); 312df3e9af8SEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel2/pc-2.7", 313b7d77f5aSDaniel P. Berrangé "-machine pc-i440fx-2.7 -cpu 486,xstore=on", 314df3e9af8SEduardo Habkost "xlevel2", 0); 315*7539fa01SThomas Huth } 3161f435716SEduardo Habkost /* 3171f435716SEduardo Habkost * QEMU 1.4.0 had auto-level enabled for CPUID[7], already, 3181f435716SEduardo Habkost * and the compat code that sets default level shouldn't 3191f435716SEduardo Habkost * disable the auto-level=7 code: 3201f435716SEduardo Habkost */ 321*7539fa01SThomas Huth if (qtest_has_machine("pc-i440fx-1.4")) { 3221f435716SEduardo Habkost add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-1.4/off", 3231f435716SEduardo Habkost "-machine pc-i440fx-1.4 -cpu Nehalem", 3241f435716SEduardo Habkost "level", 2); 3251f435716SEduardo Habkost add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-1.5/on", 326b7d77f5aSDaniel P. Berrangé "-machine pc-i440fx-1.4 -cpu Nehalem,smap=on", 3271f435716SEduardo Habkost "level", 7); 328*7539fa01SThomas Huth } 329*7539fa01SThomas Huth if (qtest_has_machine("pc-i440fx-2.3")) { 3301f435716SEduardo Habkost add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/off", 3311f435716SEduardo Habkost "-machine pc-i440fx-2.3 -cpu Penryn", 3321f435716SEduardo Habkost "level", 4); 3331f435716SEduardo Habkost add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/on", 334b7d77f5aSDaniel P. Berrangé "-machine pc-i440fx-2.3 -cpu Penryn,erms=on", 3351f435716SEduardo Habkost "level", 7); 336*7539fa01SThomas Huth } 337*7539fa01SThomas Huth if (qtest_has_machine("pc-i440fx-2.9")) { 3381f435716SEduardo Habkost add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/off", 3391f435716SEduardo Habkost "-machine pc-i440fx-2.9 -cpu Conroe", 3401f435716SEduardo Habkost "level", 10); 3411f435716SEduardo Habkost add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/on", 342b7d77f5aSDaniel P. Berrangé "-machine pc-i440fx-2.9 -cpu Conroe,erms=on", 3431f435716SEduardo Habkost "level", 10); 344*7539fa01SThomas Huth } 3451f435716SEduardo Habkost 3461f435716SEduardo Habkost /* 3471f435716SEduardo Habkost * xlevel doesn't have any feature that triggers auto-level 3481f435716SEduardo Habkost * code on old machine-types. Just check that the compat code 3491f435716SEduardo Habkost * is working correctly: 3501f435716SEduardo Habkost */ 351*7539fa01SThomas Huth if (qtest_has_machine("pc-i440fx-2.3")) { 3521f435716SEduardo Habkost add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.3", 3531f435716SEduardo Habkost "-machine pc-i440fx-2.3 -cpu SandyBridge", 3541f435716SEduardo Habkost "xlevel", 0x8000000a); 355*7539fa01SThomas Huth } 356*7539fa01SThomas Huth if (qtest_has_machine("pc-i440fx-2.4")) { 3571f435716SEduardo Habkost add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-off", 3581f435716SEduardo Habkost "-machine pc-i440fx-2.4 -cpu SandyBridge,", 3591f435716SEduardo Habkost "xlevel", 0x80000008); 3601f435716SEduardo Habkost add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-on", 361b7d77f5aSDaniel P. Berrangé "-machine pc-i440fx-2.4 -cpu SandyBridge,svm=on,npt=on", 3621f435716SEduardo Habkost "xlevel", 0x80000008); 363*7539fa01SThomas Huth } 364df3e9af8SEduardo Habkost 36517e8f541SEduardo Habkost /* Test feature parsing */ 36617e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/plus", 36717e8f541SEduardo Habkost "-cpu 486,+arat", 36817e8f541SEduardo Habkost 6, 0, "EAX", 2, true); 36917e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/minus", 37017e8f541SEduardo Habkost "-cpu pentium,-mmx", 37117e8f541SEduardo Habkost 1, 0, "EDX", 23, false); 37217e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/on", 37317e8f541SEduardo Habkost "-cpu 486,arat=on", 37417e8f541SEduardo Habkost 6, 0, "EAX", 2, true); 37517e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/off", 37617e8f541SEduardo Habkost "-cpu pentium,mmx=off", 37717e8f541SEduardo Habkost 1, 0, "EDX", 23, false); 37817e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/max-plus-invtsc", 37917e8f541SEduardo Habkost "-cpu max,+invtsc", 38017e8f541SEduardo Habkost 0x80000007, 0, "EDX", 8, true); 38117e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/max-invtsc-on", 38217e8f541SEduardo Habkost "-cpu max,invtsc=on", 38317e8f541SEduardo Habkost 0x80000007, 0, "EDX", 8, true); 38417e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/max-minus-mmx", 38517e8f541SEduardo Habkost "-cpu max,-mmx", 38617e8f541SEduardo Habkost 1, 0, "EDX", 23, false); 38717e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/max-invtsc-on,mmx=off", 38817e8f541SEduardo Habkost "-cpu max,mmx=off", 38917e8f541SEduardo Habkost 1, 0, "EDX", 23, false); 39017e8f541SEduardo Habkost 3916efef58eSEduardo Habkost return g_test_run(); 3926efef58eSEduardo Habkost } 393