16efef58eSEduardo Habkost #include "qemu/osdep.h" 26efef58eSEduardo Habkost #include "qemu-common.h" 36efef58eSEduardo Habkost #include "qapi/qmp/qdict.h" 4*47e6b297SMarkus Armbruster #include "qapi/qmp/qlist.h" 501b2ffceSMarc-André Lureau #include "qapi/qmp/qnum.h" 6a2f9976eSEduardo Habkost #include "qapi/qmp/qbool.h" 76efef58eSEduardo Habkost #include "libqtest.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 166efef58eSEduardo Habkost resp = qmp("{'execute': 'query-cpus', 'arguments': {}}"); 176efef58eSEduardo Habkost g_assert(qdict_haskey(resp, "return")); 186efef58eSEduardo Habkost ret = qdict_get_qlist(resp, "return"); 196efef58eSEduardo Habkost 206efef58eSEduardo Habkost cpu0 = qobject_to_qdict(qlist_peek(ret)); 216efef58eSEduardo Habkost path = g_strdup(qdict_get_str(cpu0, "qom_path")); 226efef58eSEduardo Habkost QDECREF(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"); 336efef58eSEduardo Habkost qobject_incref(ret); 346efef58eSEduardo Habkost QDECREF(resp); 356efef58eSEduardo Habkost return ret; 366efef58eSEduardo Habkost } 376efef58eSEduardo Habkost 3883a00f60SEduardo Habkost #ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS 39a2f9976eSEduardo Habkost static bool qom_get_bool(const char *path, const char *prop) 40a2f9976eSEduardo Habkost { 41a2f9976eSEduardo Habkost QBool *value = qobject_to_qbool(qom_get(path, prop)); 42a2f9976eSEduardo Habkost bool b = qbool_get_bool(value); 43a2f9976eSEduardo Habkost 44a2f9976eSEduardo Habkost QDECREF(value); 45a2f9976eSEduardo Habkost return b; 46a2f9976eSEduardo Habkost } 4783a00f60SEduardo Habkost #endif 48a2f9976eSEduardo Habkost 496efef58eSEduardo Habkost typedef struct CpuidTestArgs { 506efef58eSEduardo Habkost const char *cmdline; 516efef58eSEduardo Habkost const char *property; 526efef58eSEduardo Habkost int64_t expected_value; 536efef58eSEduardo Habkost } CpuidTestArgs; 546efef58eSEduardo Habkost 556efef58eSEduardo Habkost static void test_cpuid_prop(const void *data) 566efef58eSEduardo Habkost { 576efef58eSEduardo Habkost const CpuidTestArgs *args = data; 586efef58eSEduardo Habkost char *path; 5901b2ffceSMarc-André Lureau QNum *value; 6001b2ffceSMarc-André Lureau int64_t val; 616efef58eSEduardo Habkost 626efef58eSEduardo Habkost qtest_start(args->cmdline); 636efef58eSEduardo Habkost path = get_cpu0_qom_path(); 6401b2ffceSMarc-André Lureau value = qobject_to_qnum(qom_get(path, args->property)); 6501b2ffceSMarc-André Lureau g_assert(qnum_get_try_int(value, &val)); 6601b2ffceSMarc-André Lureau g_assert_cmpint(val, ==, args->expected_value); 676efef58eSEduardo Habkost qtest_end(); 686efef58eSEduardo Habkost 696efef58eSEduardo Habkost QDECREF(value); 706efef58eSEduardo Habkost g_free(path); 716efef58eSEduardo Habkost } 726efef58eSEduardo Habkost 736efef58eSEduardo Habkost static void add_cpuid_test(const char *name, const char *cmdline, 746efef58eSEduardo Habkost const char *property, int64_t expected_value) 756efef58eSEduardo Habkost { 766efef58eSEduardo Habkost CpuidTestArgs *args = g_new0(CpuidTestArgs, 1); 776efef58eSEduardo Habkost args->cmdline = cmdline; 786efef58eSEduardo Habkost args->property = property; 796efef58eSEduardo Habkost args->expected_value = expected_value; 806efef58eSEduardo Habkost qtest_add_data_func(name, args, test_cpuid_prop); 816efef58eSEduardo Habkost } 826efef58eSEduardo Habkost 8317e8f541SEduardo Habkost 8417e8f541SEduardo Habkost /* Parameters to a add_feature_test() test case */ 8517e8f541SEduardo Habkost typedef struct FeatureTestArgs { 8617e8f541SEduardo Habkost /* cmdline to start QEMU */ 8717e8f541SEduardo Habkost const char *cmdline; 8817e8f541SEduardo Habkost /* 8917e8f541SEduardo Habkost * cpuid-input-eax and cpuid-input-ecx values to look for, 9017e8f541SEduardo Habkost * in "feature-words" and "filtered-features" properties. 9117e8f541SEduardo Habkost */ 9217e8f541SEduardo Habkost uint32_t in_eax, in_ecx; 9317e8f541SEduardo Habkost /* The register name to look for, in the X86CPUFeatureWordInfo array */ 9417e8f541SEduardo Habkost const char *reg; 9517e8f541SEduardo Habkost /* The bit to check in X86CPUFeatureWordInfo.features */ 9617e8f541SEduardo Habkost int bitnr; 9717e8f541SEduardo Habkost /* The expected value for the bit in (X86CPUFeatureWordInfo.features) */ 9817e8f541SEduardo Habkost bool expected_value; 9917e8f541SEduardo Habkost } FeatureTestArgs; 10017e8f541SEduardo Habkost 10117e8f541SEduardo Habkost /* Get the value for a feature word in a X86CPUFeatureWordInfo list */ 10217e8f541SEduardo Habkost static uint32_t get_feature_word(QList *features, uint32_t eax, uint32_t ecx, 10317e8f541SEduardo Habkost const char *reg) 10417e8f541SEduardo Habkost { 10517e8f541SEduardo Habkost const QListEntry *e; 10617e8f541SEduardo Habkost 10717e8f541SEduardo Habkost for (e = qlist_first(features); e; e = qlist_next(e)) { 10817e8f541SEduardo Habkost QDict *w = qobject_to_qdict(qlist_entry_obj(e)); 10917e8f541SEduardo Habkost const char *rreg = qdict_get_str(w, "cpuid-register"); 11017e8f541SEduardo Habkost uint32_t reax = qdict_get_int(w, "cpuid-input-eax"); 11117e8f541SEduardo Habkost bool has_ecx = qdict_haskey(w, "cpuid-input-ecx"); 11217e8f541SEduardo Habkost uint32_t recx = 0; 11301b2ffceSMarc-André Lureau int64_t val; 11417e8f541SEduardo Habkost 11517e8f541SEduardo Habkost if (has_ecx) { 11617e8f541SEduardo Habkost recx = qdict_get_int(w, "cpuid-input-ecx"); 11717e8f541SEduardo Habkost } 11817e8f541SEduardo Habkost if (eax == reax && (!has_ecx || ecx == recx) && !strcmp(rreg, reg)) { 11901b2ffceSMarc-André Lureau g_assert(qnum_get_try_int(qobject_to_qnum(qdict_get(w, "features")), 12001b2ffceSMarc-André Lureau &val)); 12101b2ffceSMarc-André Lureau return val; 12217e8f541SEduardo Habkost } 12317e8f541SEduardo Habkost } 12417e8f541SEduardo Habkost return 0; 12517e8f541SEduardo Habkost } 12617e8f541SEduardo Habkost 12717e8f541SEduardo Habkost static void test_feature_flag(const void *data) 12817e8f541SEduardo Habkost { 12917e8f541SEduardo Habkost const FeatureTestArgs *args = data; 13017e8f541SEduardo Habkost char *path; 13117e8f541SEduardo Habkost QList *present, *filtered; 13217e8f541SEduardo Habkost uint32_t value; 13317e8f541SEduardo Habkost 13417e8f541SEduardo Habkost qtest_start(args->cmdline); 13517e8f541SEduardo Habkost path = get_cpu0_qom_path(); 13617e8f541SEduardo Habkost present = qobject_to_qlist(qom_get(path, "feature-words")); 13717e8f541SEduardo Habkost filtered = qobject_to_qlist(qom_get(path, "filtered-features")); 13817e8f541SEduardo Habkost value = get_feature_word(present, args->in_eax, args->in_ecx, args->reg); 13917e8f541SEduardo Habkost value |= get_feature_word(filtered, args->in_eax, args->in_ecx, args->reg); 14017e8f541SEduardo Habkost qtest_end(); 14117e8f541SEduardo Habkost 14217e8f541SEduardo Habkost g_assert(!!(value & (1U << args->bitnr)) == args->expected_value); 14317e8f541SEduardo Habkost 14417e8f541SEduardo Habkost QDECREF(present); 14517e8f541SEduardo Habkost QDECREF(filtered); 14617e8f541SEduardo Habkost g_free(path); 14717e8f541SEduardo Habkost } 14817e8f541SEduardo Habkost 14917e8f541SEduardo Habkost /* 15017e8f541SEduardo Habkost * Add test case to ensure that a given feature flag is set in 15117e8f541SEduardo Habkost * either "feature-words" or "filtered-features", when running QEMU 15217e8f541SEduardo Habkost * using cmdline 15317e8f541SEduardo Habkost */ 15417e8f541SEduardo Habkost static FeatureTestArgs *add_feature_test(const char *name, const char *cmdline, 15517e8f541SEduardo Habkost uint32_t eax, uint32_t ecx, 15617e8f541SEduardo Habkost const char *reg, int bitnr, 15717e8f541SEduardo Habkost bool expected_value) 15817e8f541SEduardo Habkost { 15917e8f541SEduardo Habkost FeatureTestArgs *args = g_new0(FeatureTestArgs, 1); 16017e8f541SEduardo Habkost args->cmdline = cmdline; 16117e8f541SEduardo Habkost args->in_eax = eax; 16217e8f541SEduardo Habkost args->in_ecx = ecx; 16317e8f541SEduardo Habkost args->reg = reg; 16417e8f541SEduardo Habkost args->bitnr = bitnr; 16517e8f541SEduardo Habkost args->expected_value = expected_value; 16617e8f541SEduardo Habkost qtest_add_data_func(name, args, test_feature_flag); 16717e8f541SEduardo Habkost return args; 16817e8f541SEduardo Habkost } 16917e8f541SEduardo Habkost 17083a00f60SEduardo Habkost #ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS 17183a00f60SEduardo Habkost static void test_plus_minus_subprocess(void) 172a2f9976eSEduardo Habkost { 173a2f9976eSEduardo Habkost char *path; 174a2f9976eSEduardo Habkost 175a2f9976eSEduardo Habkost /* Rules: 176a2f9976eSEduardo Habkost * 1)"-foo" overrides "+foo" 177a2f9976eSEduardo Habkost * 2) "[+-]foo" overrides "foo=..." 178a2f9976eSEduardo Habkost * 3) Old feature names with underscores (e.g. "sse4_2") 179a2f9976eSEduardo Habkost * should keep working 180a2f9976eSEduardo Habkost * 18183a00f60SEduardo Habkost * Note: rules 1 and 2 are planned to be removed soon, and 18283a00f60SEduardo Habkost * should generate a warning. 183a2f9976eSEduardo Habkost */ 184a2f9976eSEduardo Habkost qtest_start("-cpu pentium,-fpu,+fpu,-mce,mce=on,+cx8,cx8=off,+sse4_1,sse4_2=on"); 185a2f9976eSEduardo Habkost path = get_cpu0_qom_path(); 186a2f9976eSEduardo Habkost 187a2f9976eSEduardo Habkost g_assert_false(qom_get_bool(path, "fpu")); 188a2f9976eSEduardo Habkost g_assert_false(qom_get_bool(path, "mce")); 189a2f9976eSEduardo Habkost g_assert_true(qom_get_bool(path, "cx8")); 190a2f9976eSEduardo Habkost 191a2f9976eSEduardo Habkost /* Test both the original and the alias feature names: */ 192a2f9976eSEduardo Habkost g_assert_true(qom_get_bool(path, "sse4-1")); 193a2f9976eSEduardo Habkost g_assert_true(qom_get_bool(path, "sse4.1")); 194a2f9976eSEduardo Habkost 195a2f9976eSEduardo Habkost g_assert_true(qom_get_bool(path, "sse4-2")); 196a2f9976eSEduardo Habkost g_assert_true(qom_get_bool(path, "sse4.2")); 197a2f9976eSEduardo Habkost 198a2f9976eSEduardo Habkost qtest_end(); 199a2f9976eSEduardo Habkost g_free(path); 200a2f9976eSEduardo Habkost } 201a2f9976eSEduardo Habkost 20283a00f60SEduardo Habkost static void test_plus_minus(void) 20383a00f60SEduardo Habkost { 20483a00f60SEduardo Habkost g_test_trap_subprocess("/x86/cpuid/parsing-plus-minus/subprocess", 0, 0); 20583a00f60SEduardo Habkost g_test_trap_assert_passed(); 20683a00f60SEduardo Habkost g_test_trap_assert_stderr("*Ambiguous CPU model string. " 20783a00f60SEduardo Habkost "Don't mix both \"-mce\" and \"mce=on\"*"); 20883a00f60SEduardo Habkost g_test_trap_assert_stderr("*Ambiguous CPU model string. " 20983a00f60SEduardo Habkost "Don't mix both \"+cx8\" and \"cx8=off\"*"); 21083a00f60SEduardo Habkost g_test_trap_assert_stdout(""); 21183a00f60SEduardo Habkost } 21283a00f60SEduardo Habkost #endif 21383a00f60SEduardo Habkost 2146efef58eSEduardo Habkost int main(int argc, char **argv) 2156efef58eSEduardo Habkost { 2166efef58eSEduardo Habkost g_test_init(&argc, &argv, NULL); 2176efef58eSEduardo Habkost 21883a00f60SEduardo Habkost #ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS 21983a00f60SEduardo Habkost g_test_add_func("/x86/cpuid/parsing-plus-minus/subprocess", 22083a00f60SEduardo Habkost test_plus_minus_subprocess); 22183a00f60SEduardo Habkost g_test_add_func("/x86/cpuid/parsing-plus-minus", test_plus_minus); 22283a00f60SEduardo Habkost #endif 223a2f9976eSEduardo Habkost 2246efef58eSEduardo Habkost /* Original level values for CPU models: */ 2256efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/phenom/level", 2266efef58eSEduardo Habkost "-cpu phenom", "level", 5); 2276efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/Conroe/level", 2286efef58eSEduardo Habkost "-cpu Conroe", "level", 10); 2296efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/SandyBridge/level", 2306efef58eSEduardo Habkost "-cpu SandyBridge", "level", 0xd); 2316efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/486/xlevel", 2326efef58eSEduardo Habkost "-cpu 486", "xlevel", 0); 2336efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/core2duo/xlevel", 2346efef58eSEduardo Habkost "-cpu core2duo", "xlevel", 0x80000008); 2356efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/phenom/xlevel", 2366efef58eSEduardo Habkost "-cpu phenom", "xlevel", 0x8000001A); 2370c3d7c00SEduardo Habkost add_cpuid_test("x86/cpuid/athlon/xlevel", 2380c3d7c00SEduardo Habkost "-cpu athlon", "xlevel", 0x80000008); 2396efef58eSEduardo Habkost 2406efef58eSEduardo Habkost /* If level is not large enough, it should increase automatically: */ 241c39c0edfSEduardo Habkost /* CPUID[6].EAX: */ 242c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/phenom/arat", 243c39c0edfSEduardo Habkost "-cpu 486,+arat", "level", 6); 2446efef58eSEduardo Habkost /* CPUID[EAX=7,ECX=0].EBX: */ 2456efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/phenom/fsgsbase", 2466efef58eSEduardo Habkost "-cpu phenom,+fsgsbase", "level", 7); 247c39c0edfSEduardo Habkost /* CPUID[EAX=7,ECX=0].ECX: */ 248c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/phenom/avx512vbmi", 249c39c0edfSEduardo Habkost "-cpu phenom,+avx512vbmi", "level", 7); 250c39c0edfSEduardo Habkost /* CPUID[EAX=0xd,ECX=1].EAX: */ 251c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/phenom/xsaveopt", 252c39c0edfSEduardo Habkost "-cpu phenom,+xsaveopt", "level", 0xd); 253c39c0edfSEduardo Habkost /* CPUID[8000_0001].EDX: */ 254c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/486/3dnow", 255c39c0edfSEduardo Habkost "-cpu 486,+3dnow", "xlevel", 0x80000001); 256c39c0edfSEduardo Habkost /* CPUID[8000_0001].ECX: */ 257c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/486/sse4a", 258c39c0edfSEduardo Habkost "-cpu 486,+sse4a", "xlevel", 0x80000001); 259c39c0edfSEduardo Habkost /* CPUID[8000_0007].EDX: */ 260c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/486/invtsc", 261c39c0edfSEduardo Habkost "-cpu 486,+invtsc", "xlevel", 0x80000007); 262c39c0edfSEduardo Habkost /* CPUID[8000_000A].EDX: */ 263c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/486/npt", 264c39c0edfSEduardo Habkost "-cpu 486,+npt", "xlevel", 0x8000000A); 265c39c0edfSEduardo Habkost /* CPUID[C000_0001].EDX: */ 266c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel2/phenom/xstore", 267c39c0edfSEduardo Habkost "-cpu phenom,+xstore", "xlevel2", 0xC0000001); 2680c3d7c00SEduardo Habkost /* SVM needs CPUID[0x8000000A] */ 2690c3d7c00SEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/athlon/svm", 2700c3d7c00SEduardo Habkost "-cpu athlon,+svm", "xlevel", 0x8000000A); 271c39c0edfSEduardo Habkost 2726efef58eSEduardo Habkost 2736efef58eSEduardo Habkost /* If level is already large enough, it shouldn't change: */ 2746efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/SandyBridge/multiple", 2756efef58eSEduardo Habkost "-cpu SandyBridge,+arat,+fsgsbase,+avx512vbmi", 2766efef58eSEduardo Habkost "level", 0xd); 277c39c0edfSEduardo Habkost /* If level is explicitly set, it shouldn't change: */ 278c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/486/fixed/0xF", 279c39c0edfSEduardo Habkost "-cpu 486,level=0xF,+arat,+fsgsbase,+avx512vbmi,+xsaveopt", 280c39c0edfSEduardo Habkost "level", 0xF); 281c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/486/fixed/2", 282c39c0edfSEduardo Habkost "-cpu 486,level=2,+arat,+fsgsbase,+avx512vbmi,+xsaveopt", 283c39c0edfSEduardo Habkost "level", 2); 284c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/486/fixed/0", 285c39c0edfSEduardo Habkost "-cpu 486,level=0,+arat,+fsgsbase,+avx512vbmi,+xsaveopt", 286c39c0edfSEduardo Habkost "level", 0); 2876efef58eSEduardo Habkost 2886efef58eSEduardo Habkost /* if xlevel is already large enough, it shouldn't change: */ 2896efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/phenom/3dnow", 2900c3d7c00SEduardo Habkost "-cpu phenom,+3dnow,+sse4a,+invtsc,+npt,+svm", 2916efef58eSEduardo Habkost "xlevel", 0x8000001A); 292c39c0edfSEduardo Habkost /* If xlevel is explicitly set, it shouldn't change: */ 293c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/80000002", 2940c3d7c00SEduardo Habkost "-cpu 486,xlevel=0x80000002,+3dnow,+sse4a,+invtsc,+npt,+svm", 295c39c0edfSEduardo Habkost "xlevel", 0x80000002); 296c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/8000001A", 2970c3d7c00SEduardo Habkost "-cpu 486,xlevel=0x8000001A,+3dnow,+sse4a,+invtsc,+npt,+svm", 298c39c0edfSEduardo Habkost "xlevel", 0x8000001A); 299c39c0edfSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/phenom/fixed/0", 3000c3d7c00SEduardo Habkost "-cpu 486,xlevel=0,+3dnow,+sse4a,+invtsc,+npt,+svm", 301c39c0edfSEduardo Habkost "xlevel", 0); 3026efef58eSEduardo Habkost 3036efef58eSEduardo Habkost /* if xlevel2 is already large enough, it shouldn't change: */ 3046efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel2/486/fixed", 3056efef58eSEduardo Habkost "-cpu 486,xlevel2=0xC0000002,+xstore", 3066efef58eSEduardo Habkost "xlevel2", 0xC0000002); 3076efef58eSEduardo Habkost 308df3e9af8SEduardo Habkost /* Check compatibility of old machine-types that didn't 309df3e9af8SEduardo Habkost * auto-increase level/xlevel/xlevel2: */ 310df3e9af8SEduardo Habkost 311df3e9af8SEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/pc-2.7", 312df3e9af8SEduardo Habkost "-machine pc-i440fx-2.7 -cpu 486,+arat,+avx512vbmi,+xsaveopt", 313df3e9af8SEduardo Habkost "level", 1); 314df3e9af8SEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/pc-2.7", 3150c3d7c00SEduardo Habkost "-machine pc-i440fx-2.7 -cpu 486,+3dnow,+sse4a,+invtsc,+npt,+svm", 316df3e9af8SEduardo Habkost "xlevel", 0); 317df3e9af8SEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel2/pc-2.7", 318df3e9af8SEduardo Habkost "-machine pc-i440fx-2.7 -cpu 486,+xstore", 319df3e9af8SEduardo Habkost "xlevel2", 0); 3201f435716SEduardo Habkost /* 3211f435716SEduardo Habkost * QEMU 1.4.0 had auto-level enabled for CPUID[7], already, 3221f435716SEduardo Habkost * and the compat code that sets default level shouldn't 3231f435716SEduardo Habkost * disable the auto-level=7 code: 3241f435716SEduardo Habkost */ 3251f435716SEduardo Habkost add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-1.4/off", 3261f435716SEduardo Habkost "-machine pc-i440fx-1.4 -cpu Nehalem", 3271f435716SEduardo Habkost "level", 2); 3281f435716SEduardo Habkost add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-1.5/on", 3291f435716SEduardo Habkost "-machine pc-i440fx-1.4 -cpu Nehalem,+smap", 3301f435716SEduardo Habkost "level", 7); 3311f435716SEduardo Habkost add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/off", 3321f435716SEduardo Habkost "-machine pc-i440fx-2.3 -cpu Penryn", 3331f435716SEduardo Habkost "level", 4); 3341f435716SEduardo Habkost add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/on", 3351f435716SEduardo Habkost "-machine pc-i440fx-2.3 -cpu Penryn,+erms", 3361f435716SEduardo Habkost "level", 7); 3371f435716SEduardo Habkost add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/off", 3381f435716SEduardo Habkost "-machine pc-i440fx-2.9 -cpu Conroe", 3391f435716SEduardo Habkost "level", 10); 3401f435716SEduardo Habkost add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/on", 3411f435716SEduardo Habkost "-machine pc-i440fx-2.9 -cpu Conroe,+erms", 3421f435716SEduardo Habkost "level", 10); 3431f435716SEduardo Habkost 3441f435716SEduardo Habkost /* 3451f435716SEduardo Habkost * xlevel doesn't have any feature that triggers auto-level 3461f435716SEduardo Habkost * code on old machine-types. Just check that the compat code 3471f435716SEduardo Habkost * is working correctly: 3481f435716SEduardo Habkost */ 3491f435716SEduardo Habkost add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.3", 3501f435716SEduardo Habkost "-machine pc-i440fx-2.3 -cpu SandyBridge", 3511f435716SEduardo Habkost "xlevel", 0x8000000a); 3521f435716SEduardo Habkost add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-off", 3531f435716SEduardo Habkost "-machine pc-i440fx-2.4 -cpu SandyBridge,", 3541f435716SEduardo Habkost "xlevel", 0x80000008); 3551f435716SEduardo Habkost add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-on", 3561f435716SEduardo Habkost "-machine pc-i440fx-2.4 -cpu SandyBridge,+npt", 3571f435716SEduardo Habkost "xlevel", 0x80000008); 358df3e9af8SEduardo Habkost 35917e8f541SEduardo Habkost /* Test feature parsing */ 36017e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/plus", 36117e8f541SEduardo Habkost "-cpu 486,+arat", 36217e8f541SEduardo Habkost 6, 0, "EAX", 2, true); 36317e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/minus", 36417e8f541SEduardo Habkost "-cpu pentium,-mmx", 36517e8f541SEduardo Habkost 1, 0, "EDX", 23, false); 36617e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/on", 36717e8f541SEduardo Habkost "-cpu 486,arat=on", 36817e8f541SEduardo Habkost 6, 0, "EAX", 2, true); 36917e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/off", 37017e8f541SEduardo Habkost "-cpu pentium,mmx=off", 37117e8f541SEduardo Habkost 1, 0, "EDX", 23, false); 37217e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/max-plus-invtsc", 37317e8f541SEduardo Habkost "-cpu max,+invtsc", 37417e8f541SEduardo Habkost 0x80000007, 0, "EDX", 8, true); 37517e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/max-invtsc-on", 37617e8f541SEduardo Habkost "-cpu max,invtsc=on", 37717e8f541SEduardo Habkost 0x80000007, 0, "EDX", 8, true); 37817e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/max-minus-mmx", 37917e8f541SEduardo Habkost "-cpu max,-mmx", 38017e8f541SEduardo Habkost 1, 0, "EDX", 23, false); 38117e8f541SEduardo Habkost add_feature_test("x86/cpuid/features/max-invtsc-on,mmx=off", 38217e8f541SEduardo Habkost "-cpu max,mmx=off", 38317e8f541SEduardo Habkost 1, 0, "EDX", 23, false); 38417e8f541SEduardo Habkost 3856efef58eSEduardo Habkost return g_test_run(); 3866efef58eSEduardo Habkost } 387