Ján Tomko <jtomko(a)redhat.com> writes:
On Thu, Jul 25, 2019 at 03:52:16PM +0200, Vitaly Kuznetsov wrote:
>Support 'Direct Mode' for Hyper-V Synthetic Timers in domain config.
>Make it 'stimer' enlightenment option as it is not a separate thing.
>
>Signed-off-by: Vitaly Kuznetsov <vkuznets(a)redhat.com>
>---
> docs/formatdomain.html.in | 10 ++-
> docs/schemas/domaincommon.rng | 16 +++-
> src/conf/domain_conf.c | 138 +++++++++++++++++++++++++++++++---
> src/conf/domain_conf.h | 8 ++
> src/cpu/cpu_x86.c | 51 +++++++------
> src/cpu/cpu_x86_data.h | 2 +
> src/libvirt_private.syms | 2 +
> 7 files changed, 187 insertions(+), 40 deletions(-)
>
>diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
>index 1aaddb6d9b..a0723edad1 100644
>--- a/docs/formatdomain.html.in
>+++ b/docs/formatdomain.html.in
>@@ -2033,7 +2033,9 @@
> <vpindex state='on'/>
> <runtime state='on'/>
> <synic state='on'/>
>- <stimer state='on'/>
>+ <stimer state='on'>
>+ <direct state='on'/>
>+ </stimer>
> <reset state='on'/>
> <vendor_id state='on' value='KVM Hv'/>
> <frequencies state='on'/>
>@@ -2148,9 +2150,9 @@
> </tr>
> <tr>
> <td>stimer</td>
>- <td>Enable SynIC timers</td>
>- <td>on, off</td>
>- <td><span class="since">1.3.3 (QEMU
2.6)</span></td>
>+ <td>Enable SynIC timers, optionally with Direct Mode
support</td>
>+ <td>on, off; direct - on,off</td>
>+ <td><span class="since">1.3.3 (QEMU 2.6), direct mode
5.6.0 (QEMU 4.1)</span></td>
> </tr>
> <tr>
> <td>reset</td>
>diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
>index 763480440c..8cf1995748 100644
>--- a/docs/schemas/domaincommon.rng
>+++ b/docs/schemas/domaincommon.rng
>@@ -5896,7 +5896,7 @@
> </optional>
> <optional>
> <element name="stimer">
>- <ref name="featurestate"/>
>+ <ref name="stimer"/>
> </element>
> </optional>
> <optional>
>@@ -5945,6 +5945,20 @@
> </element>
> </define>
>
>+ <!-- Hyper-V stimer features -->
>+ <define name="stimer">
>+ <interleave>
>+ <optional>
>+ <ref name="featurestate"/>
>+ </optional>
>+ <optional>
>+ <element name="direct">
>+ <ref name="featurestate"/>
>+ </element>
>+ </optional>
>+ </interleave>
>+ </define>
>+
> <!-- Optional KVM features -->
> <define name="kvm">
> <element name="kvm">
>diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
>index 0574c69a46..779b4ed880 100644
>--- a/src/conf/domain_conf.c
>+++ b/src/conf/domain_conf.c
>@@ -197,6 +197,11 @@ VIR_ENUM_IMPL(virDomainHyperv,
> "evmcs",
> );
>
>+VIR_ENUM_IMPL(virDomainHypervStimer,
>+ VIR_DOMAIN_HYPERV_STIMER_LAST,
>+ "direct",
>+);
Do you anticipate more stimer "sub"-features in the future?
Having an enum with one value just to loop over an array with one
element and then switch()-ing across all the possible value seems
like overkill.
I don't anticipate any sub-features for stimer for the time being,
however, I wanted to make code look like what we already have
(e.g. virDomainKVM). We can, of course, simplify things if we consider
'direct' being the one and only.
>+
> VIR_ENUM_IMPL(virDomainKVM,
> VIR_DOMAIN_KVM_LAST,
> "hidden",
>@@ -20359,6 +20364,51 @@ virDomainDefParseXML(xmlDocPtr xml,
> ctxt->node = node;
> }
>
>+ if (def->features[VIR_DOMAIN_HYPERV_STIMER] == VIR_TRISTATE_SWITCH_ON) {
>+ int feature;
>+ int value;
>+ if ((n = virXPathNodeSet("./features/hyperv/stimer/*", ctxt,
&nodes)) < 0)
>+ goto error;
>+
>+ for (i = 0; i < n; i++) {
>+ feature = virDomainHypervStimerTypeFromString((const char
*)nodes[i]->name);
>+ if (feature < 0) {
>+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
>+ _("unsupported Hyper-V stimer feature:
%s"),
>+ nodes[i]->name);
>+ goto error;
>+ }
>+
>+ switch ((virDomainHypervStimer) feature) {
>+ case VIR_DOMAIN_HYPERV_STIMER_DIRECT:
>+ if (!(tmp = virXMLPropString(nodes[i], "state"))) {
>+ virReportError(VIR_ERR_XML_ERROR,
>+ _("missing 'state' attribute for
"
>+ "Hyper-V stimer feature
'%s'"),
>+ nodes[i]->name);
>+ goto error;
>+ }
>+
>+ if ((value = virTristateSwitchTypeFromString(tmp)) < 0) {
>+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
>+ _("invalid value of state argument
"
>+ "for Hyper-V stimer feature
'%s'"),
>+ nodes[i]->name);
>+ goto error;
>+ }
>+
>+ VIR_FREE(tmp);
>+ def->hyperv_stimer_features[feature] = value;
>+ break;
>+
>+ /* coverity[dead_error_begin] */
>+ case VIR_DOMAIN_HYPERV_STIMER_LAST:
>+ break;
>+ }
>+ }
>+ VIR_FREE(nodes);
>+ }
>+
> if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
> int feature;
> int value;
>@@ -22583,6 +22633,29 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src,
> }
> }
>
>+ if (src->hyperv_features[VIR_DOMAIN_HYPERV_STIMER] == VIR_TRISTATE_SWITCH_ON)
{
>+ for (i = 0; i < VIR_DOMAIN_HYPERV_STIMER_LAST; i++) {
>+ switch ((virDomainHypervStimer) i) {
>+ case VIR_DOMAIN_HYPERV_STIMER_DIRECT:
>+ if (src->hyperv_stimer_features[i] !=
dst->hyperv_stimer_features[i]) {
>+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
>+ _("State of HyperV stimer feature
'%s' differs: "
>+ "source: '%s', destination:
'%s'"),
>+ virDomainHypervStimerTypeToString(i),
>+
virTristateSwitchTypeToString(src->hyperv_stimer_features[i]),
>+
virTristateSwitchTypeToString(dst->hyperv_stimer_features[i]));
>+ return false;
>+ }
>+
>+ break;
>+
>+ /* coverity[dead_error_begin] */
>+ case VIR_DOMAIN_HYPERV_STIMER_LAST:
>+ break;
>+ }
>+ }
>+ }
>+
> /* kvm */
> if (src->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
> for (i = 0; i < VIR_DOMAIN_KVM_LAST; i++) {
>@@ -28017,6 +28090,8 @@ virDomainDefFormatFeatures(virBufferPtr buf,
> virBufferAddLit(&childBuf, "<hyperv>\n");
> virBufferAdjustIndent(&childBuf, 2);
> for (j = 0; j < VIR_DOMAIN_HYPERV_LAST; j++) {
>+ size_t k;
>+
> if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ABSENT)
> continue;
>
>@@ -28031,35 +28106,76 @@ virDomainDefFormatFeatures(virBufferPtr buf,
> case VIR_DOMAIN_HYPERV_VPINDEX:
> case VIR_DOMAIN_HYPERV_RUNTIME:
> case VIR_DOMAIN_HYPERV_SYNIC:
>- case VIR_DOMAIN_HYPERV_STIMER:
> case VIR_DOMAIN_HYPERV_RESET:
> case VIR_DOMAIN_HYPERV_FREQUENCIES:
> case VIR_DOMAIN_HYPERV_REENLIGHTENMENT:
> case VIR_DOMAIN_HYPERV_TLBFLUSH:
> case VIR_DOMAIN_HYPERV_IPI:
> case VIR_DOMAIN_HYPERV_EVMCS:
>+ virBufferAddLit(&childBuf, "/>\n");
Changing all the cases to print the ending tag themselves in a separate
commit first would make this one look nicer.
Ok.
> break;
>
>- case VIR_DOMAIN_HYPERV_SPINLOCKS:
>- if (def->hyperv_features[j] != VIR_TRISTATE_SWITCH_ON)
>+ case VIR_DOMAIN_HYPERV_STIMER:
>+ if (def->hyperv_features[j] != VIR_TRISTATE_SWITCH_ON) {
>+ virBufferAddLit(&childBuf, "/>\n");
>+ break;
>+ }
>+
>diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
>index 48b0af4b04..fc12887fc3 100644
>--- a/src/conf/domain_conf.h
>+++ b/src/conf/domain_conf.h
>@@ -1762,6 +1762,12 @@ typedef enum {
> VIR_DOMAIN_HYPERV_LAST
> } virDomainHyperv;
>
>+typedef enum {
>+ VIR_DOMAIN_HYPERV_STIMER_DIRECT = 0,
>+
>+ VIR_DOMAIN_HYPERV_STIMER_LAST
>+} virDomainHypervStimer;
>+
> typedef enum {
> VIR_DOMAIN_KVM_HIDDEN = 0,
>
>@@ -2400,6 +2406,7 @@ struct _virDomainDef {
> int kvm_features[VIR_DOMAIN_KVM_LAST];
> int msrs_features[VIR_DOMAIN_MSRS_LAST];
> unsigned int hyperv_spinlocks;
>+ int hyperv_stimer_features[VIR_DOMAIN_HYPERV_STIMER_LAST];
How about:
int hyperv_stimer_direct;
Yes, if we decide to drop the virDomainHypervStimer.
> virGICVersion gic_version;
> virDomainHPTResizing hpt_resizing;
> unsigned long long hpt_maxpagesize; /* Stored in KiB */
>@@ -3420,6 +3427,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceStreamingMode);
> VIR_ENUM_DECL(virDomainGraphicsSpiceMouseMode);
> VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy);
> VIR_ENUM_DECL(virDomainHyperv);
>+VIR_ENUM_DECL(virDomainHypervStimer);
> VIR_ENUM_DECL(virDomainKVM);
> VIR_ENUM_DECL(virDomainMsrsUnknown);
> VIR_ENUM_DECL(virDomainRNGModel);
>diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
>index 55b55da784..4fb9e6a4df 100644
>--- a/src/cpu/cpu_x86.c
>+++ b/src/cpu/cpu_x86.c
>@@ -59,9 +59,9 @@ struct _virCPUx86Feature {
> { .type = VIR_CPU_X86_DATA_CPUID, \
> .data = { .cpuid = {__VA_ARGS__} } }
>
>-#define KVM_FEATURE_DEF(Name, Eax_in, Eax) \
>+#define KVM_FEATURE_DEF(Name, Eax_in, Eax, Edx) \
> static virCPUx86DataItem Name ## _data[] = { \
>- CPUID(.eax_in = Eax_in, .eax = Eax), \
>+ CPUID(.eax_in = Eax_in, .eax = Eax, .edx = Edx), \
Another change that can be separated.
Yes if we still need it) I haven't looked at Jirka's series to check if
we still check CPUID for Hyper-V features or we only check QEMU command
line now.
> }
>
> #define KVM_FEATURE(Name) \
>@@ -74,49 +74,51 @@ struct _virCPUx86Feature {
> }
>
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_CLOCKSOURCE,
>- 0x40000001, 0x00000001);
>+ 0x40000001, 0x00000001, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_NOP_IO_DELAY,
>- 0x40000001, 0x00000002);
>+ 0x40000001, 0x00000002, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_MMU_OP,
>- 0x40000001, 0x00000004);
>+ 0x40000001, 0x00000004, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_CLOCKSOURCE2,
>- 0x40000001, 0x00000008);
>+ 0x40000001, 0x00000008, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_ASYNC_PF,
>- 0x40000001, 0x00000010);
>+ 0x40000001, 0x00000010, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_STEAL_TIME,
>- 0x40000001, 0x00000020);
>+ 0x40000001, 0x00000020, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_PV_EOI,
>- 0x40000001, 0x00000040);
>+ 0x40000001, 0x00000040, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_PV_UNHALT,
>- 0x40000001, 0x00000080);
>+ 0x40000001, 0x00000080, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_CLOCKSOURCE_STABLE_BIT,
>- 0x40000001, 0x01000000);
>+ 0x40000001, 0x01000000, 0x0);
Take a look at Jirka's series which removes most of these.
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_RUNTIME,
>- 0x40000003, 0x00000001);
>+ 0x40000003, 0x00000001, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_SYNIC,
>- 0x40000003, 0x00000004);
>+ 0x40000003, 0x00000004, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_STIMER,
>- 0x40000003, 0x00000008);
>+ 0x40000003, 0x00000008, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_RELAXED,
>- 0x40000003, 0x00000020);
>+ 0x40000003, 0x00000020, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_SPINLOCKS,
>- 0x40000003, 0x00000022);
>+ 0x40000003, 0x00000022, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_VAPIC,
>- 0x40000003, 0x00000030);
>+ 0x40000003, 0x00000030, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_VPINDEX,
>- 0x40000003, 0x00000040);
>+ 0x40000003, 0x00000040, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_RESET,
>- 0x40000003, 0x00000080);
>+ 0x40000003, 0x00000080, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_FREQUENCIES,
>- 0x40000003, 0x00000800);
>+ 0x40000003, 0x00000800, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_REENLIGHTENMENT,
>- 0x40000003, 0x00002000);
>+ 0x40000003, 0x00002000, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_TLBFLUSH,
>- 0x40000004, 0x00000004);
>+ 0x40000004, 0x00000004, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_IPI,
>- 0x40000004, 0x00000400);
>+ 0x40000004, 0x00000400, 0x0);
> KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_EVMCS,
>- 0x40000004, 0x00004000);
>+ 0x40000004, 0x00004000, 0x0);
>+KVM_FEATURE_DEF(VIR_CPU_x86_KVM_HV_STIMER_DIRECT,
>+ 0x40000003, 0x0, 0x00080000);
>
> static virCPUx86Feature x86_kvm_features[] =
> {
>@@ -142,6 +144,7 @@ static virCPUx86Feature x86_kvm_features[] =
> KVM_FEATURE(VIR_CPU_x86_KVM_HV_TLBFLUSH),
> KVM_FEATURE(VIR_CPU_x86_KVM_HV_IPI),
> KVM_FEATURE(VIR_CPU_x86_KVM_HV_EVMCS),
>+ KVM_FEATURE(VIR_CPU_x86_KVM_HV_STIMER_DIRECT),
> };
>
> typedef struct _virCPUx86Model virCPUx86Model;
>diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
>index f3f4d7ab9c..198f19e037 100644
>--- a/src/cpu/cpu_x86_data.h
>+++ b/src/cpu/cpu_x86_data.h
>@@ -72,6 +72,8 @@ struct _virCPUx86MSR {
> #define VIR_CPU_x86_KVM_HV_IPI "__kvm_hv_ipi"
> #define VIR_CPU_x86_KVM_HV_EVMCS "__kvm_hv_evmcs"
>
>+/* Hyper-V Synthetic Timer (virDomainHypervStimer) features */
>+#define VIR_CPU_x86_KVM_HV_STIMER_DIRECT "__kvm_hv_stimer_direct"
"hv-stimer-direct"
to correctly detect its availability
Yes, I'll rebase on top of Jirka's series. Thanks!
>
> #define VIR_CPU_X86_DATA_INIT { 0 }
>
Jano
--
Vitaly