1*6efef58eSEduardo Habkost #include "qemu/osdep.h" 2*6efef58eSEduardo Habkost #include "qemu-common.h" 3*6efef58eSEduardo Habkost #include "qapi/qmp/qlist.h" 4*6efef58eSEduardo Habkost #include "qapi/qmp/qdict.h" 5*6efef58eSEduardo Habkost #include "qapi/qmp/qint.h" 6*6efef58eSEduardo Habkost #include "libqtest.h" 7*6efef58eSEduardo Habkost 8*6efef58eSEduardo Habkost static char *get_cpu0_qom_path(void) 9*6efef58eSEduardo Habkost { 10*6efef58eSEduardo Habkost QDict *resp; 11*6efef58eSEduardo Habkost QList *ret; 12*6efef58eSEduardo Habkost QDict *cpu0; 13*6efef58eSEduardo Habkost char *path; 14*6efef58eSEduardo Habkost 15*6efef58eSEduardo Habkost resp = qmp("{'execute': 'query-cpus', 'arguments': {}}"); 16*6efef58eSEduardo Habkost g_assert(qdict_haskey(resp, "return")); 17*6efef58eSEduardo Habkost ret = qdict_get_qlist(resp, "return"); 18*6efef58eSEduardo Habkost 19*6efef58eSEduardo Habkost cpu0 = qobject_to_qdict(qlist_peek(ret)); 20*6efef58eSEduardo Habkost path = g_strdup(qdict_get_str(cpu0, "qom_path")); 21*6efef58eSEduardo Habkost QDECREF(resp); 22*6efef58eSEduardo Habkost return path; 23*6efef58eSEduardo Habkost } 24*6efef58eSEduardo Habkost 25*6efef58eSEduardo Habkost static QObject *qom_get(const char *path, const char *prop) 26*6efef58eSEduardo Habkost { 27*6efef58eSEduardo Habkost QDict *resp = qmp("{ 'execute': 'qom-get'," 28*6efef58eSEduardo Habkost " 'arguments': { 'path': %s," 29*6efef58eSEduardo Habkost " 'property': %s } }", 30*6efef58eSEduardo Habkost path, prop); 31*6efef58eSEduardo Habkost QObject *ret = qdict_get(resp, "return"); 32*6efef58eSEduardo Habkost qobject_incref(ret); 33*6efef58eSEduardo Habkost QDECREF(resp); 34*6efef58eSEduardo Habkost return ret; 35*6efef58eSEduardo Habkost } 36*6efef58eSEduardo Habkost 37*6efef58eSEduardo Habkost typedef struct CpuidTestArgs { 38*6efef58eSEduardo Habkost const char *cmdline; 39*6efef58eSEduardo Habkost const char *property; 40*6efef58eSEduardo Habkost int64_t expected_value; 41*6efef58eSEduardo Habkost } CpuidTestArgs; 42*6efef58eSEduardo Habkost 43*6efef58eSEduardo Habkost static void test_cpuid_prop(const void *data) 44*6efef58eSEduardo Habkost { 45*6efef58eSEduardo Habkost const CpuidTestArgs *args = data; 46*6efef58eSEduardo Habkost char *path; 47*6efef58eSEduardo Habkost QInt *value; 48*6efef58eSEduardo Habkost 49*6efef58eSEduardo Habkost qtest_start(args->cmdline); 50*6efef58eSEduardo Habkost path = get_cpu0_qom_path(); 51*6efef58eSEduardo Habkost value = qobject_to_qint(qom_get(path, args->property)); 52*6efef58eSEduardo Habkost g_assert_cmpint(qint_get_int(value), ==, args->expected_value); 53*6efef58eSEduardo Habkost qtest_end(); 54*6efef58eSEduardo Habkost 55*6efef58eSEduardo Habkost QDECREF(value); 56*6efef58eSEduardo Habkost g_free(path); 57*6efef58eSEduardo Habkost } 58*6efef58eSEduardo Habkost 59*6efef58eSEduardo Habkost static void add_cpuid_test(const char *name, const char *cmdline, 60*6efef58eSEduardo Habkost const char *property, int64_t expected_value) 61*6efef58eSEduardo Habkost { 62*6efef58eSEduardo Habkost CpuidTestArgs *args = g_new0(CpuidTestArgs, 1); 63*6efef58eSEduardo Habkost args->cmdline = cmdline; 64*6efef58eSEduardo Habkost args->property = property; 65*6efef58eSEduardo Habkost args->expected_value = expected_value; 66*6efef58eSEduardo Habkost qtest_add_data_func(name, args, test_cpuid_prop); 67*6efef58eSEduardo Habkost } 68*6efef58eSEduardo Habkost 69*6efef58eSEduardo Habkost int main(int argc, char **argv) 70*6efef58eSEduardo Habkost { 71*6efef58eSEduardo Habkost g_test_init(&argc, &argv, NULL); 72*6efef58eSEduardo Habkost 73*6efef58eSEduardo Habkost /* Original level values for CPU models: */ 74*6efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/phenom/level", 75*6efef58eSEduardo Habkost "-cpu phenom", "level", 5); 76*6efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/Conroe/level", 77*6efef58eSEduardo Habkost "-cpu Conroe", "level", 10); 78*6efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/SandyBridge/level", 79*6efef58eSEduardo Habkost "-cpu SandyBridge", "level", 0xd); 80*6efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/486/xlevel", 81*6efef58eSEduardo Habkost "-cpu 486", "xlevel", 0); 82*6efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/core2duo/xlevel", 83*6efef58eSEduardo Habkost "-cpu core2duo", "xlevel", 0x80000008); 84*6efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/phenom/xlevel", 85*6efef58eSEduardo Habkost "-cpu phenom", "xlevel", 0x8000001A); 86*6efef58eSEduardo Habkost 87*6efef58eSEduardo Habkost /* If level is not large enough, it should increase automatically: */ 88*6efef58eSEduardo Habkost /* CPUID[EAX=7,ECX=0].EBX: */ 89*6efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/phenom/fsgsbase", 90*6efef58eSEduardo Habkost "-cpu phenom,+fsgsbase", "level", 7); 91*6efef58eSEduardo Habkost 92*6efef58eSEduardo Habkost /* If level is already large enough, it shouldn't change: */ 93*6efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/auto-level/SandyBridge/multiple", 94*6efef58eSEduardo Habkost "-cpu SandyBridge,+arat,+fsgsbase,+avx512vbmi", 95*6efef58eSEduardo Habkost "level", 0xd); 96*6efef58eSEduardo Habkost 97*6efef58eSEduardo Habkost /* if xlevel is already large enough, it shouldn't change: */ 98*6efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel/phenom/3dnow", 99*6efef58eSEduardo Habkost "-cpu phenom,+3dnow,+sse4a,+invtsc,+npt", 100*6efef58eSEduardo Habkost "xlevel", 0x8000001A); 101*6efef58eSEduardo Habkost 102*6efef58eSEduardo Habkost /* if xlevel2 is already large enough, it shouldn't change: */ 103*6efef58eSEduardo Habkost add_cpuid_test("x86/cpuid/auto-xlevel2/486/fixed", 104*6efef58eSEduardo Habkost "-cpu 486,xlevel2=0xC0000002,+xstore", 105*6efef58eSEduardo Habkost "xlevel2", 0xC0000002); 106*6efef58eSEduardo Habkost 107*6efef58eSEduardo Habkost return g_test_run(); 108*6efef58eSEduardo Habkost } 109