Add a schema for QAPI definitions that will be used by *-user. Example output: $ ./QMP/qmp --path=/tmp/m qom-get --path=/machine/unattached/device[1] --property=feature-words item[0].cpuid-register: EDX item[0].cpuid-input-eax: 2147483658 item[0].features: 0 item[1].cpuid-register: EAX item[1].cpuid-input-eax: 1073741825 item[1].features: 0 item[2].cpuid-register: EDX item[2].cpuid-input-eax: 3221225473 item[2].features: 0 item[3].cpuid-register: ECX item[3].cpuid-input-eax: 2147483649 item[3].features: 101 item[4].cpuid-register: EDX item[4].cpuid-input-eax: 2147483649 item[4].features: 563346425 item[5].cpuid-register: EBX item[5].cpuid-input-eax: 7 item[5].features: 0 item[5].cpuid-input-ecx: 0 item[6].cpuid-register: ECX item[6].cpuid-input-eax: 1 item[6].features: 2155880449 item[7].cpuid-register: EDX item[7].cpuid-input-eax: 1 item[7].features: 126614521 Signed-off-by: Eduardo Habkost <ehabkost@xxxxxxxxxx> --- * I am sending this as a separated patch so both alternatives (with qapi and without qapi) can be compared and get feedback. * Current solution is not based on the "feature word array" patch, but it may be easily rebased and simplified if we decide to include the CPUX86State feature_words array later. Signed-off-by: Eduardo Habkost <ehabkost@xxxxxxxxxx> --- .gitignore | 2 ++ Makefile | 11 ++++++ Makefile.objs | 5 +++ cpu-qapi-schema.json | 31 ++++++++++++++++ target-i386/Makefile.objs | 1 + target-i386/cpu-qapi-schema.json | 31 ++++++++++++++++ target-i386/cpu.c | 78 ++++++++++++++++++++++++---------------- 7 files changed, 128 insertions(+), 31 deletions(-) create mode 100644 cpu-qapi-schema.json create mode 100644 target-i386/cpu-qapi-schema.json diff --git a/.gitignore b/.gitignore index 487813a..71408e3 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,8 @@ linux-headers/asm qapi-generated qapi-types.[ch] qapi-visit.[ch] +cpu-qapi-types.[ch] +cpu-qapi-visit.[ch] qmp-commands.h qmp-marshal.c qemu-doc.html diff --git a/Makefile b/Makefile index 80344d9..efa2971 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,9 @@ GENERATED_HEADERS = config-host.h qemu-options.def GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c +GENERATED_HEADERS += cpu-qapi-types.h cpu-qapi-visit.h +GENERATED_SOURCES += cpu-qapi-types.c cpu-qapi-visit.c + GENERATED_HEADERS += trace/generated-events.h GENERATED_SOURCES += trace/generated-events.c @@ -209,6 +212,14 @@ qmp-commands.h qmp-marshal.c :\ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@") +cpu-qapi-types.c cpu-qapi-types.h :\ +$(SRC_PATH)/cpu-qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." -p "cpu-" < $<, " GEN $@") +cpu-qapi-visit.c cpu-qapi-visit.h :\ +$(SRC_PATH)/cpu-qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py) + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." -p "cpu-" < $<, " GEN $@") + + QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h) $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN) diff --git a/Makefile.objs b/Makefile.objs index f99841c..4099dbb 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -91,6 +91,11 @@ common-obj-y += qmp-marshal.o qapi-visit.o qapi-types.o common-obj-y += qmp.o hmp.o endif +###################################################################### +# qapi types used by both system and user emulation: + +common-obj-y += cpu-qapi-types.o cpu-qapi-visit.o + ####################################################################### # Target-independent parts used in system and user emulation common-obj-y += qemu-log.o diff --git a/cpu-qapi-schema.json b/cpu-qapi-schema.json new file mode 100644 index 0000000..0ecf528 --- /dev/null +++ b/cpu-qapi-schema.json @@ -0,0 +1,31 @@ +## +# @X86CPURegister32 +# +# A X86 32-bit register +# +# Since: 1.5 +## +{ 'enum': 'X86CPURegister32', + 'data': [ 'EAX', 'EBX', 'ECX', 'EDX', 'ESP', 'EBP', 'ESI', 'EDI' ] } + +## +# @X86CPUFeatureWordInfo +# +# Information about a X86 CPU feature word +# +# @cpuid-input-eax: Input EAX value for CPUID instruction for that feature word +# +# @cpuid-input-ecx: #optional Input ECX value for CPUID instruction for that +# feature word +# +# @cpuid-register: Output register containing the feature bits +# +# @features: value of output register, containing the feature bits +# +# Since: 1.5 +## +{ 'type': 'X86CPUFeatureWordInfo', + 'data': { 'cpuid-input-eax': 'int', + '*cpuid-input-ecx': 'int', + 'cpuid-register': 'X86CPURegister32', + 'features': 'int' } } diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs index c1d4f05..8b0b483 100644 --- a/target-i386/Makefile.objs +++ b/target-i386/Makefile.objs @@ -6,3 +6,4 @@ obj-$(CONFIG_KVM) += kvm.o hyperv.o obj-$(CONFIG_NO_KVM) += kvm-stub.o obj-$(CONFIG_LINUX_USER) += ioport-user.o obj-$(CONFIG_BSD_USER) += ioport-user.o + diff --git a/target-i386/cpu-qapi-schema.json b/target-i386/cpu-qapi-schema.json new file mode 100644 index 0000000..0ecf528 --- /dev/null +++ b/target-i386/cpu-qapi-schema.json @@ -0,0 +1,31 @@ +## +# @X86CPURegister32 +# +# A X86 32-bit register +# +# Since: 1.5 +## +{ 'enum': 'X86CPURegister32', + 'data': [ 'EAX', 'EBX', 'ECX', 'EDX', 'ESP', 'EBP', 'ESI', 'EDI' ] } + +## +# @X86CPUFeatureWordInfo +# +# Information about a X86 CPU feature word +# +# @cpuid-input-eax: Input EAX value for CPUID instruction for that feature word +# +# @cpuid-input-ecx: #optional Input ECX value for CPUID instruction for that +# feature word +# +# @cpuid-register: Output register containing the feature bits +# +# @features: value of output register, containing the feature bits +# +# Since: 1.5 +## +{ 'type': 'X86CPUFeatureWordInfo', + 'data': { 'cpuid-input-eax': 'int', + '*cpuid-input-ecx': 'int', + 'cpuid-register': 'X86CPURegister32', + 'features': 'int' } } diff --git a/target-i386/cpu.c b/target-i386/cpu.c index ebf6358..ccd7a27 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -30,6 +30,8 @@ #include "qemu/config-file.h" #include "qapi/qmp/qerror.h" +#include "cpu-qapi-types.h" +#include "cpu-qapi-visit.h" #include "qapi/visitor.h" #include "sysemu/arch_init.h" @@ -194,16 +196,26 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { }, }; -static const char *reg_names_32[CPU_NB_REGS32] = { - [R_EAX] = "EAX", - [R_ECX] = "ECX", - [R_EDX] = "EDX", - [R_EBX] = "EBX", - [R_ESP] = "ESP", - [R_EBP] = "EBP", - [R_ESI] = "ESI", - [R_EDI] = "EDI", +typedef struct X86RegisterInfo32 { + /* Name of 32-bit register */ + const char *name; + /* QAPI enum value for 32-bit register */ + X86CPURegister32 qapi_enum; +} X86RegisterInfo32; + +#define REGISTER(reg) \ + [R_##reg] = { .name = #reg, .qapi_enum = X86_C_P_U_REGISTER32_##reg } +X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = { + REGISTER(EAX), + REGISTER(ECX), + REGISTER(EDX), + REGISTER(EBX), + REGISTER(ESP), + REGISTER(EBP), + REGISTER(ESI), + REGISTER(EDI), }; +#undef REGISTER const char *get_register_name_32(unsigned int reg) @@ -211,7 +223,7 @@ const char *get_register_name_32(unsigned int reg) if (reg > CPU_NB_REGS32) { return NULL; } - return reg_names_32[reg]; + return x86_reg_info_32[reg].name; } /* collects per-function cpuid data @@ -1284,34 +1296,38 @@ static void x86_cpu_get_feature_words(Object *obj, Visitor *v, void *opaque, CPUX86State *env = &cpu->env; FeatureWord w; Error *err = NULL; - uint32_t feat_values[FEATURE_WORDS] = { }; + X86CPUFeatureWordInfo word_infos[FEATURE_WORDS] = { }; + X86CPUFeatureWordInfoList list_entries[FEATURE_WORDS] = { }; + X86CPUFeatureWordInfoList *list = NULL; /* We need to set the entries one-by-one, by now, while we don't have * a single feature_words array on X86CPU */ - feat_values[FEAT_1_EDX] = env->cpuid_features; - feat_values[FEAT_1_ECX] = env->cpuid_ext_features; - feat_values[FEAT_8000_0001_EDX] = env->cpuid_ext2_features; - feat_values[FEAT_8000_0001_ECX] = env->cpuid_ext3_features; - feat_values[FEAT_C000_0001_EDX] = env->cpuid_ext4_features; - feat_values[FEAT_KVM] = env->cpuid_kvm_features; - feat_values[FEAT_SVM] = env->cpuid_svm_features; - feat_values[FEAT_7_0_EBX] = env->cpuid_7_0_ebx_features; - - visit_start_list(v, "feature-words", &err); + word_infos[FEAT_1_EDX].features = env->cpuid_features; + word_infos[FEAT_1_ECX].features = env->cpuid_ext_features; + word_infos[FEAT_8000_0001_EDX].features = env->cpuid_ext2_features; + word_infos[FEAT_8000_0001_ECX].features = env->cpuid_ext3_features; + word_infos[FEAT_C000_0001_EDX].features = env->cpuid_ext4_features; + word_infos[FEAT_KVM].features = env->cpuid_kvm_features; + word_infos[FEAT_SVM].features = env->cpuid_svm_features; + word_infos[FEAT_7_0_EBX].features = env->cpuid_7_0_ebx_features; + + /* Build the rest of the list fields */ for (w = 0; w < FEATURE_WORDS; w++) { FeatureWordInfo *wi = &feature_word_info[w]; - visit_start_struct(v, NULL, NULL, NULL, 0, &err); - visit_type_uint32(v, &wi->cpuid_eax, "cpuid-input-eax", &err); - if (wi->cpuid_needs_ecx) { - visit_type_uint32(v, &wi->cpuid_ecx, "cpuid-input-ecx", &err); - } - visit_type_enum(v, &wi->cpuid_reg, reg_names_32, "x86-register-32", - "cpuid-register", &err); - visit_type_uint32(v, &feat_values[w], "features", &err); - visit_end_struct(v, &err); + X86CPUFeatureWordInfo *qwi = &word_infos[w]; + qwi->cpuid_input_eax = wi->cpuid_eax; + qwi->has_cpuid_input_ecx = wi->cpuid_needs_ecx; + qwi->cpuid_input_ecx = wi->cpuid_ecx; + qwi->cpuid_register = x86_reg_info_32[wi->cpuid_reg].qapi_enum; + + /* List will be in reverse order, but order shouldn't matter */ + list_entries[w].next = list; + list_entries[w].value = &word_infos[w]; + list = &list_entries[w]; } - visit_end_list(v, &err); + + visit_type_X86CPUFeatureWordInfoList(v, &list, "feature-words", &err); error_propagate(errp, err); } -- 1.8.1.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list