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(a)redhat.com>
---
* 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(a)redhat.com>
---
.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