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>
This commit is contained in:
parent
bd87d2a2c0
commit
8e8aba5054
@ -79,10 +79,15 @@ common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y)
|
||||
######################################################################
|
||||
# qapi
|
||||
|
||||
common-obj-y += qmp-marshal.o qapi-visit.o qapi-types.o
|
||||
common-obj-y += qmp-marshal.o
|
||||
common-obj-y += qmp.o hmp.o
|
||||
endif
|
||||
|
||||
######################################################################
|
||||
# some qapi visitors are used by both system and user emulation:
|
||||
|
||||
common-obj-y += qapi-visit.o qapi-types.o
|
||||
|
||||
#######################################################################
|
||||
# Target-independent parts used in system and user emulation
|
||||
common-obj-y += qemu-log.o
|
||||
|
@ -3587,3 +3587,35 @@
|
||||
##
|
||||
{'command': 'query-command-line-options', 'data': { '*option': 'str' },
|
||||
'returns': ['CommandLineOptionInfo'] }
|
||||
|
||||
##
|
||||
# @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' } }
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user