The clock timer XML is being updated in the following ways (based on further off-list discussion that was missed during the initial implementation): 1) 'wallclock' is changed to 'track', and the possible values are 'boot' (corresponds to old 'host'), 'guest', and 'wall'. 2) 'mode' has an additional value 'smpsafe' 3) when tickpolicy='catchup', there can be an optional sub-element of timer called 'catchup': <catchup threshold=123 slew=120 limit=10000/> Those three values are all longs, always optional, and if they are present, they are positive. Internally, 0 indicates "unspecified". * docs/schemas/domain.rng: updated RNG definition to account for changes * src/conf/domain_conf.h: change the C struct and enums to match changes. * src/conf/domain_conf.c: timer parse and format functions changed to handle the new selections and new element. * src/libvirt_private.syms: *TimerWallclock* changes to *TimerTrack* * src/qemu/qemu_conf.c: again, account for Wallclock --> Track change. --- docs/schemas/domain.rng | 24 +++++++++++- src/conf/domain_conf.c | 89 +++++++++++++++++++++++++++++++++++---------- src/conf/domain_conf.h | 26 ++++++++++---- src/libvirt_private.syms | 4 +- src/qemu/qemu_conf.c | 17 +++++++-- 5 files changed, 126 insertions(+), 34 deletions(-) diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index d804301..228665c 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -344,10 +344,11 @@ </choice> </attribute> <optional> - <attribute name="wallclock"> + <attribute name="track"> <choice> - <value>host</value> + <value>boot</value> <value>guest</value> + <value>wall</value> </choice> </attribute> </optional> @@ -362,6 +363,9 @@ </attribute> </optional> <optional> + <ref name="catchup"/> + </optional> + <optional> <attribute name="frequency"> <ref name="unsignedInt"/> </attribute> @@ -373,6 +377,7 @@ <value>native</value> <value>emulate</value> <value>paravirt</value> + <value>smpsafe</value> </choice> </attribute> </optional> @@ -387,6 +392,21 @@ <empty/> </element> </define> + <define name="catchup"> + <element name="catchup"> + <optional> + <attribute name="threshold"> + <ref name="unsignedInt"/> + </attribute> + <attribute name="slew"> + <ref name="unsignedInt"/> + </attribute> + <attribute name="limit"> + <ref name="unsignedInt"/> + </attribute> + </optional> + </element> + </define> <!-- A bootloader may be used to extract the OS information instead of defining the OS parameter in the instance. It points just to the diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 66aa53e..b8acab9 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -252,9 +252,10 @@ VIR_ENUM_IMPL(virDomainTimerName, VIR_DOMAIN_TIMER_NAME_LAST, "hpet", "tsc"); -VIR_ENUM_IMPL(virDomainTimerWallclock, VIR_DOMAIN_TIMER_WALLCLOCK_LAST, - "host", - "guest"); +VIR_ENUM_IMPL(virDomainTimerTrack, VIR_DOMAIN_TIMER_TRACK_LAST, + "boot", + "guest", + "wall"); VIR_ENUM_IMPL(virDomainTimerTickpolicy, VIR_DOMAIN_TIMER_TICKPOLICY_LAST, "delay", @@ -266,7 +267,8 @@ VIR_ENUM_IMPL(virDomainTimerMode, VIR_DOMAIN_TIMER_MODE_LAST, "auto", "native", "emulate", - "paravirt"); + "paravirt", + "smpsafe"); #define virDomainReportError(code, ...) \ virReportErrorHelper(NULL, VIR_FROM_DOMAIN, code, __FILE__, \ @@ -2555,7 +2557,7 @@ virDomainTimerDefParseXML(const xmlNodePtr node, char *name = NULL; char *present = NULL; char *tickpolicy = NULL; - char *wallclock = NULL; + char *track = NULL; char *mode = NULL; virDomainTimerDefPtr def; @@ -2603,12 +2605,12 @@ virDomainTimerDefParseXML(const xmlNodePtr node, } } - def->wallclock = -1; - wallclock = virXMLPropString(node, "wallclock"); - if (wallclock != NULL) { - if ((def->wallclock = virDomainTimerWallclockTypeFromString(wallclock)) < 0) { + def->track = -1; + track = virXMLPropString(node, "track"); + if (track != NULL) { + if ((def->track = virDomainTimerTrackTypeFromString(track)) < 0) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, - _("unknown timer wallclock '%s'"), wallclock); + _("unknown timer track '%s'"), track); goto error; } } @@ -2616,7 +2618,7 @@ virDomainTimerDefParseXML(const xmlNodePtr node, int ret = virXPathULong("string(./frequency)", ctxt, &def->frequency); if (ret == -1) { def->frequency = 0; - } else if (ret <= 0) { + } else if (ret < 0) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("invalid timer frequency")); goto error; @@ -2632,11 +2634,42 @@ virDomainTimerDefParseXML(const xmlNodePtr node, } } + xmlNodePtr catchup = virXPathNode("./catchup", ctxt); + if (catchup != NULL) { + ret = virXPathULong("string(./catchup/@threshold)", ctxt, + &def->catchup.threshold); + if (ret == -1) { + def->catchup.threshold = 0; + } else if (ret < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("invalid catchup threshold")); + goto error; + } + + ret = virXPathULong("string(./catchup/@slew)", ctxt, &def->catchup.slew); + if (ret == -1) { + def->catchup.slew = 0; + } else if (ret < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("invalid catchup slew")); + goto error; + } + + ret = virXPathULong("string(./catchup/@limit)", ctxt, &def->catchup.limit); + if (ret == -1) { + def->catchup.limit = 0; + } else if (ret < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("invalid catchup limit")); + goto error; + } + } + cleanup: VIR_FREE(name); VIR_FREE(present); VIR_FREE(tickpolicy); - VIR_FREE(wallclock); + VIR_FREE(track); VIR_FREE(mode); ctxt->node = oldnode; @@ -5456,16 +5489,16 @@ virDomainTimerDefFormat(virBufferPtr buf, if ((def->name == VIR_DOMAIN_TIMER_NAME_PLATFORM) || (def->name == VIR_DOMAIN_TIMER_NAME_RTC)) { - if (def->wallclock != -1) { - const char *wallclock - = virDomainTimerWallclockTypeToString(def->wallclock); - if (!wallclock) { + if (def->track != -1) { + const char *track + = virDomainTimerTrackTypeToString(def->track); + if (!track) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, - _("unexpected timer wallclock %d"), - def->wallclock); + _("unexpected timer track %d"), + def->track); return -1; } - virBufferVSprintf(buf, " wallclock='%s'", wallclock); + virBufferVSprintf(buf, " track='%s'", track); } } @@ -5487,7 +5520,23 @@ virDomainTimerDefFormat(virBufferPtr buf, } } - virBufferAddLit(buf, "/>\n"); + if ((def->catchup.threshold == 0) + && (def->catchup.slew == 0) + && (def->catchup.limit == 0)) { + virBufferAddLit(buf, "/>\n"); + } else { + virBufferAddLit(buf, ">\n <catchup "); + if (def->catchup.threshold > 0) { + virBufferVSprintf(buf, " threshold='%lu'", def->catchup.threshold); + } + if (def->catchup.slew > 0) { + virBufferVSprintf(buf, " slew='%lu'", def->catchup.slew); + } + if (def->catchup.limit > 0) { + virBufferVSprintf(buf, " limit='%lu'", def->catchup.limit); + } + virBufferAddLit(buf, "/>\n </timer>\n"); + } return 0; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index ed1a4ad..435d546 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -656,11 +656,12 @@ enum virDomainTimerNameType { VIR_DOMAIN_TIMER_NAME_LAST, }; -enum virDomainTimerWallclockType { - VIR_DOMAIN_TIMER_WALLCLOCK_HOST = 0, - VIR_DOMAIN_TIMER_WALLCLOCK_GUEST, +enum virDomainTimerTrackType { + VIR_DOMAIN_TIMER_TRACK_BOOT = 0, + VIR_DOMAIN_TIMER_TRACK_GUEST, + VIR_DOMAIN_TIMER_TRACK_WALL, - VIR_DOMAIN_TIMER_WALLCLOCK_LAST, + VIR_DOMAIN_TIMER_TRACK_LAST, }; enum virDomainTimerTickpolicyType { @@ -677,10 +678,19 @@ enum virDomainTimerModeType { VIR_DOMAIN_TIMER_MODE_NATIVE, VIR_DOMAIN_TIMER_MODE_EMULATE, VIR_DOMAIN_TIMER_MODE_PARAVIRT, + VIR_DOMAIN_TIMER_MODE_SMPSAFE, VIR_DOMAIN_TIMER_MODE_LAST, }; +typedef struct _virDomainTimerCatchupDef virDomainTimerCatchupDef; +typedef virDomainTimerCatchupDef *virDomainTimerCatchupDefPtr; +struct _virDomainTimerCatchupDef { + unsigned long threshold; + unsigned long slew; + unsigned long limit; +}; + typedef struct _virDomainTimerDef virDomainTimerDef; typedef virDomainTimerDef *virDomainTimerDefPtr; struct _virDomainTimerDef { @@ -688,8 +698,10 @@ struct _virDomainTimerDef { int present; /* unspecified = -1, no = 0, yes = 1 */ int tickpolicy; /* none|catchup|merge|discard */ - /* wallclock is only valid for name='platform|rtc' */ - int wallclock; /* host|guest */ + virDomainTimerCatchupDef catchup; + + /* track is only valid for name='platform|rtc' */ + int track; /* host|guest */ /* frequency & mode are only valid for name='tsc' */ unsigned long frequency; /* in Hz, unspecified = 0 */ @@ -1029,7 +1041,7 @@ VIR_ENUM_DECL(virDomainClockOffset) VIR_ENUM_DECL(virDomainNetdevMacvtap) VIR_ENUM_DECL(virDomainTimerName) -VIR_ENUM_DECL(virDomainTimerWallclock) +VIR_ENUM_DECL(virDomainTimerTrack) VIR_ENUM_DECL(virDomainTimerTickpolicy) VIR_ENUM_DECL(virDomainTimerMode) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index cc943f8..08a6b97 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -199,8 +199,8 @@ virDomainClockOffsetTypeFromString; virDomainDiskErrorPolicyTypeToString; virDomainTimerNameTypeToString; virDomainTimerNameTypeFromString; -virDomainTimerWallclockTypeToString; -virDomainTimerWallclockTypeFromString; +virDomainTimerTrackTypeToString; +virDomainTimerTrackTypeFromString; virDomainTimerTickpolicyTypeToString; virDomainTimerTickpolicyTypeFromString; virDomainTimerModeTypeToString; diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 8f6f7ec..4f279be 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -3183,11 +3183,22 @@ qemuBuildClockArgStr(virDomainClockDefPtr def) int i; for (i = 0; i < def->ntimers; i++) { if (def->timers[i]->name == VIR_DOMAIN_TIMER_NAME_RTC) { - if (def->timers[i]->wallclock == VIR_DOMAIN_TIMER_WALLCLOCK_HOST) { - virBufferAddLit(&buf, ",clock=host"); - } else if (def->timers[i]->wallclock == VIR_DOMAIN_TIMER_WALLCLOCK_GUEST) { + switch (def->timers[i]->track) { + case -1: /* unspecified - use hypervisor default */ + break; + case VIR_DOMAIN_TIMER_TRACK_BOOT: + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported rtc timer track '%s'"), + virDomainTimerTrackTypeToString(def->timers[i]->track)); + goto error; + case VIR_DOMAIN_TIMER_TRACK_GUEST: virBufferAddLit(&buf, ",clock=vm"); + break; + case VIR_DOMAIN_TIMER_TRACK_WALL: + virBufferAddLit(&buf, ",clock=host"); + break; } + switch (def->timers[i]->tickpolicy) { case -1: case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY: -- 1.6.6.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list