diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index a18119f9a08e1b15d0547d56d5094f80cd31cce5..fcb7c59c00d8aa815ff30a7a931bfb32f89d5858 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'/>
@@ -2149,9 +2151,9 @@
stimer |
- Enable SynIC timers |
- on, off |
- 1.3.3 (QEMU 2.6) |
+ Enable SynIC timers, optionally with Direct Mode support |
+ on, off; direct - on,off |
+ 1.3.3 (QEMU 2.6), direct mode 5.7.0 (QEMU 4.1) |
reset |
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 08853f9d9e9216a0082cbccd170dded49839b357..c48f8c4f56f44149cf5f2d7219837fe2b5c81a08 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -5907,7 +5907,7 @@
-
+
@@ -5956,6 +5956,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 8642927d6bf3c931f887ba1398efd7aa2c0444ce..617ccac4a538f8ebefa346b858ce73688292aede 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -20394,6 +20394,39 @@ virDomainDefParseXML(xmlDocPtr xml,
ctxt->node = node;
}
+ if (def->features[VIR_DOMAIN_HYPERV_STIMER] == VIR_TRISTATE_SWITCH_ON) {
+ int value;
+ if ((n = virXPathNodeSet("./features/hyperv/stimer/*", ctxt, &nodes)) < 0)
+ goto error;
+
+ for (i = 0; i < n; i++) {
+ if (STRNEQ((const char *)nodes[i]->name, "direct")) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported Hyper-V stimer feature: %s"),
+ nodes[i]->name);
+ goto error;
+ }
+
+ if (!(tmp = virXMLPropString(nodes[i], "state"))) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("missing 'state' attribute for "
+ "Hyper-V stimer '%s' feature"), "direct");
+ goto error;
+ }
+
+ if ((value = virTristateSwitchTypeFromString(tmp)) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("invalid value of state argument "
+ "for Hyper-V stimer '%s' feature"), "direct");
+ goto error;
+ }
+
+ VIR_FREE(tmp);
+ def->hyperv_stimer_direct = value;
+ }
+ VIR_FREE(nodes);
+ }
+
if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
int feature;
int value;
@@ -22619,6 +22652,17 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src,
}
}
+ if (src->hyperv_features[VIR_DOMAIN_HYPERV_STIMER] == VIR_TRISTATE_SWITCH_ON) {
+ if (src->hyperv_stimer_direct != dst->hyperv_stimer_direct) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("State of HyperV stimer direct feature differs: "
+ "source: '%s', destination: '%s'"),
+ virTristateSwitchTypeToString(src->hyperv_stimer_direct),
+ virTristateSwitchTypeToString(dst->hyperv_stimer_direct));
+ return false;
+ }
+ }
+
/* kvm */
if (src->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
for (i = 0; i < VIR_DOMAIN_KVM_LAST; i++) {
@@ -28079,7 +28123,6 @@ 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:
@@ -28098,6 +28141,23 @@ virDomainDefFormatFeatures(virBufferPtr buf,
def->hyperv_spinlocks);
break;
+ case VIR_DOMAIN_HYPERV_STIMER:
+ if (def->hyperv_features[j] != VIR_TRISTATE_SWITCH_ON) {
+ virBufferAddLit(&childBuf, "/>\n");
+ break;
+ }
+ if (def->hyperv_stimer_direct == VIR_TRISTATE_SWITCH_ON) {
+ virBufferAddLit(&childBuf, ">\n");
+ virBufferAdjustIndent(&childBuf, 2);
+ virBufferAddLit(&childBuf, "\n");
+ virBufferAdjustIndent(&childBuf, -2);
+ virBufferAddLit(&childBuf, "\n");
+ } else {
+ virBufferAddLit(&childBuf, "/>\n");
+ }
+
+ break;
+
case VIR_DOMAIN_HYPERV_VENDOR_ID:
if (def->hyperv_features[j] != VIR_TRISTATE_SWITCH_ON) {
virBufferAddLit(&childBuf, "/>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index f7423b1b6f89d69b1e909e21af0655616d86fb4c..cbe7b611702edc1d240102d976d430122d38bac6 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2401,6 +2401,7 @@ struct _virDomainDef {
int kvm_features[VIR_DOMAIN_KVM_LAST];
int msrs_features[VIR_DOMAIN_MSRS_LAST];
unsigned int hyperv_spinlocks;
+ int hyperv_stimer_direct;
virGICVersion gic_version;
virDomainHPTResizing hpt_resizing;
unsigned long long hpt_maxpagesize; /* Stored in KiB */
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index d2d9537c3261de7df8cb2eb4620c9c1877853c25..32b9836dd5e4fe55fa26b8fe3dd47878fa962846 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -100,6 +100,8 @@ KVM_FEATURE_DEF(VIR_CPU_x86_HV_IPI,
0x40000004, 0x00000400, 0x0);
KVM_FEATURE_DEF(VIR_CPU_x86_HV_EVMCS,
0x40000004, 0x00004000, 0x0);
+KVM_FEATURE_DEF(VIR_CPU_x86_HV_STIMER_DIRECT,
+ 0x40000003, 0x0, 0x00080000);
static virCPUx86Feature x86_kvm_features[] =
{
@@ -116,6 +118,7 @@ static virCPUx86Feature x86_kvm_features[] =
KVM_FEATURE(VIR_CPU_x86_HV_TLBFLUSH),
KVM_FEATURE(VIR_CPU_x86_HV_IPI),
KVM_FEATURE(VIR_CPU_x86_HV_EVMCS),
+ KVM_FEATURE(VIR_CPU_x86_HV_STIMER_DIRECT),
};
typedef struct _virCPUx86Model virCPUx86Model;
diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
index cc0c93dff012b3c2135780bbe4affea7c6da2afd..cebf3b6669e05f61b4dfc8697cbb6befc40d031d 100644
--- a/src/cpu/cpu_x86_data.h
+++ b/src/cpu/cpu_x86_data.h
@@ -64,6 +64,8 @@ struct _virCPUx86MSR {
#define VIR_CPU_x86_HV_IPI "hv-ipi"
#define VIR_CPU_x86_HV_EVMCS "hv-evmcs"
+/* Hyper-V Synthetic Timer option */
+#define VIR_CPU_x86_HV_STIMER_DIRECT "hv-stimer-direct"
#define VIR_CPU_X86_DATA_INIT { 0 }