mirror of https://gitee.com/openkylin/libvirt.git
Changes to clock timer XML to match final design.
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.
This commit is contained in:
parent
8a7b4be5ab
commit
4ee2b31804
|
@ -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>
|
||||
|
@ -361,6 +362,9 @@
|
|||
</choice>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="catchup"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="frequency">
|
||||
<ref name="unsignedInt"/>
|
||||
|
@ -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
|
||||
|
|
|
@ -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__, \
|
||||
|
@ -2575,7 +2577,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;
|
||||
|
@ -2623,12 +2625,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;
|
||||
}
|
||||
}
|
||||
|
@ -2636,7 +2638,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;
|
||||
|
@ -2652,11 +2654,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;
|
||||
|
||||
|
@ -5474,16 +5507,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5505,7 +5538,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;
|
||||
}
|
||||
|
|
|
@ -659,11 +659,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 {
|
||||
|
@ -680,10 +681,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 {
|
||||
|
@ -691,8 +701,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 */
|
||||
|
@ -1032,7 +1044,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)
|
||||
|
||||
|
|
|
@ -199,8 +199,8 @@ virDomainClockOffsetTypeFromString;
|
|||
virDomainDiskErrorPolicyTypeToString;
|
||||
virDomainTimerNameTypeToString;
|
||||
virDomainTimerNameTypeFromString;
|
||||
virDomainTimerWallclockTypeToString;
|
||||
virDomainTimerWallclockTypeFromString;
|
||||
virDomainTimerTrackTypeToString;
|
||||
virDomainTimerTrackTypeFromString;
|
||||
virDomainTimerTickpolicyTypeToString;
|
||||
virDomainTimerTickpolicyTypeFromString;
|
||||
virDomainTimerModeTypeToString;
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue