Some of the emulator features are presented in the <features> element in
the domain XML although they are virtual CPUID feature bits when
presented to the guest. To avoid confusing the users with these
features, as they are not configurable via the <cpu> element, this patch
adds an internal array where those can be stored privately instead of
exposing them in the XML.
Additionaly KVM feature bits are added as example usage of this code.
---
src/cpu/cpu_x86.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/cpu/cpu_x86_data.h | 12 ++++++++++
2 files changed, 75 insertions(+)
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index e91cf49..c972709 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -56,6 +56,25 @@ struct x86_feature {
struct x86_feature *next;
};
+struct x86_kvm_feature {
+ const char *name;
+ const virCPUx86CPUID cpuid;
+};
+
+static const struct x86_kvm_feature x86_kvm_features[] =
+{
+ {VIR_CPU_x86_KVM_CLOCKSOURCE, { .function = 0x40000001, .eax = 0x00000001 }},
+ {VIR_CPU_x86_KVM_NOP_IO_DELAY, { .function = 0x40000001, .eax = 0x00000002 }},
+ {VIR_CPU_x86_KVM_MMU_OP, { .function = 0x40000001, .eax = 0x00000004 }},
+ {VIR_CPU_x86_KVM_CLOCKSOURCE2, { .function = 0x40000001, .eax = 0x00000008 }},
+ {VIR_CPU_x86_KVM_ASYNC_PF, { .function = 0x40000001, .eax = 0x00000010 }},
+ {VIR_CPU_x86_KVM_STEAL_TIME, { .function = 0x40000001, .eax = 0x00000020 }},
+ {VIR_CPU_x86_KVM_PV_EOI, { .function = 0x40000001, .eax = 0x00000040 }},
+ {VIR_CPU_x86_KVM_PV_UNHALT, { .function = 0x40000001, .eax = 0x00000080 }},
+ {VIR_CPU_x86_KVM_CLOCKSOURCE_STABLE_BIT,
+ { .function = 0x40000001, .eax = 0x01000000 }},
+};
+
struct x86_model {
char *name;
const struct x86_vendor *vendor;
@@ -1068,6 +1087,47 @@ x86MapLoadCallback(enum cpuMapElement element,
}
+static int
+x86MapLoadInternalFeatures(struct x86_map *map)
+{
+ size_t i;
+ struct x86_feature *feature = NULL;
+
+ for (i = 0; i < ARRAY_CARDINALITY(x86_kvm_features); i++) {
+ const char *name = x86_kvm_features[i].name;
+
+ if (x86FeatureFind(map, name)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("CPU feature %s already defined"), name);
+ return -1;
+ }
+
+ if (!(feature = x86FeatureNew()))
+ goto error;
+
+ if (VIR_STRDUP(feature->name, name) < 0)
+ goto error;
+
+ if (virCPUx86DataAddCPUID(feature->data, &x86_kvm_features[i].cpuid))
+ goto error;
+
+ if (map->features == NULL) {
+ map->features = feature;
+ } else {
+ feature->next = map->features;
+ map->features = feature;
+ }
+
+ feature = NULL;
+ }
+
+ return 0;
+
+error:
+ x86FeatureFree(feature);
+ return -1;
+}
+
int
virCPUx86MapOnceInit(void)
{
@@ -1079,6 +1139,9 @@ virCPUx86MapOnceInit(void)
if (cpuMapLoad("x86", x86MapLoadCallback, map) < 0)
goto error;
+ if (x86MapLoadInternalFeatures(map) < 0)
+ goto error;
+
virCPUx86Map = map;
return 0;
diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
index 69066f1..88dccf6 100644
--- a/src/cpu/cpu_x86_data.h
+++ b/src/cpu/cpu_x86_data.h
@@ -36,8 +36,20 @@ struct _virCPUx86CPUID {
};
# define CPUX86_BASIC 0x0
+# define CPUX86_KVM 0x40000000
# define CPUX86_EXTENDED 0x80000000
+# define VIR_CPU_x86_KVM_CLOCKSOURCE "__kvm_clocksource"
+# define VIR_CPU_x86_KVM_NOP_IO_DELAY "__kvm_no_io_delay"
+# define VIR_CPU_x86_KVM_MMU_OP "__kvm_mmu_op"
+# define VIR_CPU_x86_KVM_CLOCKSOURCE2 "__kvm_clocksource2"
+# define VIR_CPU_x86_KVM_ASYNC_PF "__kvm_async_pf"
+# define VIR_CPU_x86_KVM_STEAL_TIME "__kvm_steal_time"
+# define VIR_CPU_x86_KVM_PV_EOI "__kvm_pv_eoi"
+# define VIR_CPU_x86_KVM_PV_UNHALT "__kvm_pv_unhalt"
+# define VIR_CPU_x86_KVM_CLOCKSOURCE_STABLE_BIT "__kvm_clocksource_stable"
+
+
typedef struct _virCPUx86Data virCPUx86Data;
struct _virCPUx86Data {
size_t len;
--
1.8.3.2