diff options
author | Eduardo Habkost <ehabkost@redhat.com> | 2013-05-06 13:20:07 -0300 |
---|---|---|
committer | Andreas Färber <afaerber@suse.de> | 2013-05-06 19:16:05 +0200 |
commit | 8e8aba5054c043027445c880fcb9dbc8f6a217f3 (patch) | |
tree | b661977e19826b6952deb44bd45a282cf279fe63 /target-i386 | |
parent | bd87d2a2c05569a28768648b069cbc24c40f4fb8 (diff) | |
download | qemu-8e8aba5054c043027445c880fcb9dbc8f6a217f3.zip qemu-8e8aba5054c043027445c880fcb9dbc8f6a217f3.tar.gz qemu-8e8aba5054c043027445c880fcb9dbc8f6a217f3.tar.bz2 |
target-i386: Add "feature-words" property to X86CPU
This property will be useful for libvirt, as libvirt already has logic
based on low-level feature bits (not feature names), so it will be
really easy to convert the current libvirt logic to something using the
"feature-words" property.
The property will have two main use cases:
- Checking host capabilities, by checking the features of the "host"
CPU model
- Checking which features are enabled on each CPU model
Example output:
$ ./QMP/qmp --path=/tmp/m \
qom-get --path=/machine/icc-bridge/icc/child[0] \
--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@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/cpu.c | 70 |
1 files changed, 58 insertions, 12 deletions
diff --git a/target-i386/cpu.c b/target-i386/cpu.c index a39b364..3857514 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 "qapi-types.h" +#include "qapi-visit.h" #include "qapi/visitor.h" #include "sysemu/arch_init.h" @@ -195,23 +197,34 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { }, }; +typedef struct X86RegisterInfo32 { + /* Name of register */ + const char *name; + /* QAPI enum value 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) { - static const char *reg_names[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", - }; - if (reg > CPU_NB_REGS32) { return NULL; } - return reg_names[reg]; + return x86_reg_info_32[reg].name; } /* collects per-function cpuid data @@ -1405,6 +1418,36 @@ static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, void *opaque, cpu->env.cpuid_apic_id = value; } +static void x86_cpu_get_feature_words(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + X86CPU *cpu = X86_CPU(obj); + CPUX86State *env = &cpu->env; + FeatureWord w; + Error *err = NULL; + X86CPUFeatureWordInfo word_infos[FEATURE_WORDS] = { }; + X86CPUFeatureWordInfoList list_entries[FEATURE_WORDS] = { }; + X86CPUFeatureWordInfoList *list = NULL; + + for (w = 0; w < FEATURE_WORDS; w++) { + FeatureWordInfo *wi = &feature_word_info[w]; + 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; + qwi->features = env->features[w]; + + /* 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_type_X86CPUFeatureWordInfoList(v, &list, "feature-words", &err); + error_propagate(errp, err); +} + static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name) { x86_def_t *def; @@ -2396,6 +2439,9 @@ static void x86_cpu_initfn(Object *obj) object_property_add(obj, "apic-id", "int", x86_cpuid_get_apic_id, x86_cpuid_set_apic_id, NULL, NULL, NULL); + object_property_add(obj, "feature-words", "X86CPUFeatureWordInfo", + x86_cpu_get_feature_words, + NULL, NULL, NULL, NULL); env->cpuid_apic_id = x86_cpu_apic_id_from_index(cs->cpu_index); |