[libvirt] [PATCH 0/4] Xen: Improve support for <timer> configurations

This series fixes some issues wrt <timer> configuration in the libxl driver and the xenconfig parser/formatter. See patches 1 and 2 for details on the libxl driver changes, and patch 3 for details on the xenconfig parser/formatter changes. Patch 4 adds some tests to check domXML <-> xl.cfg conversions of <timer> configuration. Jim Fehlig (4): libxl: fix timer configuration libxl: support emulate mode of tsc timer xenconfig: add support for more timers tests: add xlconfig tests for <timer> configurations src/libxl/libxl_conf.c | 49 +++++++++---- src/xenconfig/xen_common.c | 87 +++++++++++++++++++++--- tests/xlconfigdata/test-fullvirt-hpet-timer.cfg | 27 ++++++++ tests/xlconfigdata/test-fullvirt-hpet-timer.xml | 64 +++++++++++++++++ tests/xlconfigdata/test-fullvirt-multi-timer.cfg | 28 ++++++++ tests/xlconfigdata/test-fullvirt-multi-timer.xml | 65 ++++++++++++++++++ tests/xlconfigdata/test-fullvirt-tsc-timer.cfg | 27 ++++++++ tests/xlconfigdata/test-fullvirt-tsc-timer.xml | 64 +++++++++++++++++ tests/xlconfigtest.c | 3 + 9 files changed, 392 insertions(+), 22 deletions(-) create mode 100644 tests/xlconfigdata/test-fullvirt-hpet-timer.cfg create mode 100644 tests/xlconfigdata/test-fullvirt-hpet-timer.xml create mode 100644 tests/xlconfigdata/test-fullvirt-multi-timer.cfg create mode 100644 tests/xlconfigdata/test-fullvirt-multi-timer.xml create mode 100644 tests/xlconfigdata/test-fullvirt-tsc-timer.cfg create mode 100644 tests/xlconfigdata/test-fullvirt-tsc-timer.xml -- 2.9.2

The current logic around configuring timers in libxl based on virDomainDef object is a bit brain dead. Unsupported timers are silently ignored and tsc is only recognized if it is the first timer specified. Change the logic to reject unsupported timers and honor the tsc timer regardless of its order when multiple timers are specified. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_conf.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index a24f9e0..3e6d623 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -313,9 +313,10 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, for (i = 0; i < virDomainDefGetVcpus(def); i++) libxl_bitmap_set((&b_info->avail_vcpus), i); - if (def->clock.ntimers > 0 && - def->clock.timers[0]->name == VIR_DOMAIN_TIMER_NAME_TSC) { - switch (def->clock.timers[0]->mode) { + for (i = 0; i < def->clock.ntimers; i++) { + switch ((virDomainTimerNameType) def->clock.timers[i]->name) { + case VIR_DOMAIN_TIMER_NAME_TSC: + switch (def->clock.timers[i]->mode) { case VIR_DOMAIN_TIMER_MODE_NATIVE: b_info->tsc_mode = 2; break; @@ -324,8 +325,35 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, break; default: b_info->tsc_mode = 1; + } + break; + + case VIR_DOMAIN_TIMER_NAME_HPET: + if (!hvm) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + return -1; + } + if (def->clock.timers[i]->present == 1) + libxl_defbool_set(&b_info->u.hvm.hpet, 1); + break; + + case VIR_DOMAIN_TIMER_NAME_PLATFORM: + case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: + case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK: + case VIR_DOMAIN_TIMER_NAME_RTC: + case VIR_DOMAIN_TIMER_NAME_PIT: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + return -1; + + case VIR_DOMAIN_TIMER_NAME_LAST: + break; } } + b_info->sched_params.weight = 1000; b_info->max_memkb = virDomainDefGetMemoryInitial(def); b_info->target_memkb = def->mem.cur_balloon; @@ -341,12 +369,6 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_defbool_set(&b_info->u.hvm.acpi, def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_TRISTATE_SWITCH_ON); - for (i = 0; i < def->clock.ntimers; i++) { - if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET && - def->clock.timers[i]->present == 1) { - libxl_defbool_set(&b_info->u.hvm.hpet, 1); - } - } if (def->nsounds > 0) { /* -- 2.9.2

On 01/20/2017 01:59 AM, Jim Fehlig wrote:
The current logic around configuring timers in libxl based on virDomainDef object is a bit brain dead. Unsupported timers are silently ignored and tsc is only recognized if it is the first timer specified.
Change the logic to reject unsupported timers and honor the tsc timer regardless of its order when multiple timers are specified.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_conf.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index a24f9e0..3e6d623 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -313,9 +313,10 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, for (i = 0; i < virDomainDefGetVcpus(def); i++) libxl_bitmap_set((&b_info->avail_vcpus), i);
- if (def->clock.ntimers > 0 && - def->clock.timers[0]->name == VIR_DOMAIN_TIMER_NAME_TSC) { - switch (def->clock.timers[0]->mode) { + for (i = 0; i < def->clock.ntimers; i++) { + switch ((virDomainTimerNameType) def->clock.timers[i]->name) { + case VIR_DOMAIN_TIMER_NAME_TSC: + switch (def->clock.timers[i]->mode) { case VIR_DOMAIN_TIMER_MODE_NATIVE: b_info->tsc_mode = 2; break; @@ -324,8 +325,35 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, break; default: b_info->tsc_mode = 1; + } + break; + + case VIR_DOMAIN_TIMER_NAME_HPET: + if (!hvm) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + return -1; + } + if (def->clock.timers[i]->present == 1) + libxl_defbool_set(&b_info->u.hvm.hpet, 1); + break; + + case VIR_DOMAIN_TIMER_NAME_PLATFORM: + case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: + case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK: Interestingly, and looking at the code [toolstack: tools/libxl/libxl_dom.c:hvm_set_viridian_features(), hypervisor: xen/arch/x86/hvm/viridian.c:update_reference_tsc()] it looks like that to some extent we support the Hyper-V Reference TSC page (Hyper-V Clock?) but it is kept disabled in the viridian base features in libxl. Even if we wanted to enable it would have to be more specific than adding <viridian /> feature like with:
libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_BASE); libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_TSC); and perhaps behind "#ifdef LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_TSC" as this is only supported since Xen 4.6.0? And I think it would work with tsc_mode not being emulated? Relevant commit on Xen is dd94caca5 ("x86/viridian: add Partition Reference Time enlightenment") Anyhow this is probably not in the context of this series, just food for thought in case we want to have in the future.
+ case VIR_DOMAIN_TIMER_NAME_RTC: + case VIR_DOMAIN_TIMER_NAME_PIT: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + return -1; + + case VIR_DOMAIN_TIMER_NAME_LAST: + break; } } + Spurious whitespace? Or perhaps it was purposely added?
b_info->sched_params.weight = 1000; b_info->max_memkb = virDomainDefGetMemoryInitial(def); b_info->target_memkb = def->mem.cur_balloon; @@ -341,12 +369,6 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_defbool_set(&b_info->u.hvm.acpi, def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_TRISTATE_SWITCH_ON); - for (i = 0; i < def->clock.ntimers; i++) { - if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET && - def->clock.timers[i]->present == 1) { - libxl_defbool_set(&b_info->u.hvm.hpet, 1); - } - }
if (def->nsounds > 0) { /*

On 01/20/2017 05:00 AM, Joao Martins wrote:
On 01/20/2017 01:59 AM, Jim Fehlig wrote:
The current logic around configuring timers in libxl based on virDomainDef object is a bit brain dead. Unsupported timers are silently ignored and tsc is only recognized if it is the first timer specified.
Change the logic to reject unsupported timers and honor the tsc timer regardless of its order when multiple timers are specified.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_conf.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index a24f9e0..3e6d623 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -313,9 +313,10 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, for (i = 0; i < virDomainDefGetVcpus(def); i++) libxl_bitmap_set((&b_info->avail_vcpus), i);
- if (def->clock.ntimers > 0 && - def->clock.timers[0]->name == VIR_DOMAIN_TIMER_NAME_TSC) { - switch (def->clock.timers[0]->mode) { + for (i = 0; i < def->clock.ntimers; i++) { + switch ((virDomainTimerNameType) def->clock.timers[i]->name) { + case VIR_DOMAIN_TIMER_NAME_TSC: + switch (def->clock.timers[i]->mode) { case VIR_DOMAIN_TIMER_MODE_NATIVE: b_info->tsc_mode = 2; break; @@ -324,8 +325,35 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, break; default: b_info->tsc_mode = 1; + } + break; + + case VIR_DOMAIN_TIMER_NAME_HPET: + if (!hvm) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + return -1; + } + if (def->clock.timers[i]->present == 1) + libxl_defbool_set(&b_info->u.hvm.hpet, 1); + break; + + case VIR_DOMAIN_TIMER_NAME_PLATFORM: + case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: + case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK: Interestingly, and looking at the code [toolstack: tools/libxl/libxl_dom.c:hvm_set_viridian_features(), hypervisor: xen/arch/x86/hvm/viridian.c:update_reference_tsc()] it looks like that to some extent we support the Hyper-V Reference TSC page (Hyper-V Clock?) but it is kept disabled in the viridian base features in libxl. Even if we wanted to enable it would have to be more specific than adding <viridian /> feature like with:
libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_BASE);
I'd think <viridian/> OS feature would enable LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_BASE
libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_TSC);
And this one would be enabled with <clock> <timer name='hypervclock'/> </clock> Is that correct? Should a hypervclock timer also include LIBXL_VIRIDIAN_ENLIGHTENMENT_TIME_REF_COUNT?
and perhaps behind "#ifdef LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_TSC" as this is only supported since Xen 4.6.0? And I think it would work with tsc_mode not being emulated? Relevant commit on Xen is dd94caca5 ("x86/viridian: add Partition Reference Time enlightenment") Anyhow this is probably not in the context of this series, just food for thought in case we want to have in the future.
Good points, and agree they could be addressed in a followup series that enables viridian enlightenments.
+ case VIR_DOMAIN_TIMER_NAME_RTC: + case VIR_DOMAIN_TIMER_NAME_PIT: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + return -1; + + case VIR_DOMAIN_TIMER_NAME_LAST: + break; } } + Spurious whitespace? Or perhaps it was purposely added?
Initially I think it was spurious, but looking again I think it brings some needed whitespace between these sections of code. Regards, Jim
b_info->sched_params.weight = 1000; b_info->max_memkb = virDomainDefGetMemoryInitial(def); b_info->target_memkb = def->mem.cur_balloon; @@ -341,12 +369,6 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_defbool_set(&b_info->u.hvm.acpi, def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_TRISTATE_SWITCH_ON); - for (i = 0; i < def->clock.ntimers; i++) { - if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET && - def->clock.timers[i]->present == 1) { - libxl_defbool_set(&b_info->u.hvm.hpet, 1); - } - }
if (def->nsounds > 0) { /*

On 01/20/2017 09:55 PM, Jim Fehlig wrote:
On 01/20/2017 05:00 AM, Joao Martins wrote:
On 01/20/2017 01:59 AM, Jim Fehlig wrote:
The current logic around configuring timers in libxl based on virDomainDef object is a bit brain dead. Unsupported timers are silently ignored and tsc is only recognized if it is the first timer specified.
Change the logic to reject unsupported timers and honor the tsc timer regardless of its order when multiple timers are specified.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_conf.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-)
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index a24f9e0..3e6d623 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -313,9 +313,10 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, for (i = 0; i < virDomainDefGetVcpus(def); i++) libxl_bitmap_set((&b_info->avail_vcpus), i);
- if (def->clock.ntimers > 0 && - def->clock.timers[0]->name == VIR_DOMAIN_TIMER_NAME_TSC) { - switch (def->clock.timers[0]->mode) { + for (i = 0; i < def->clock.ntimers; i++) { + switch ((virDomainTimerNameType) def->clock.timers[i]->name) { + case VIR_DOMAIN_TIMER_NAME_TSC: + switch (def->clock.timers[i]->mode) { case VIR_DOMAIN_TIMER_MODE_NATIVE: b_info->tsc_mode = 2; break; @@ -324,8 +325,35 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, break; default: b_info->tsc_mode = 1; + } + break; + + case VIR_DOMAIN_TIMER_NAME_HPET: + if (!hvm) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + return -1; + } + if (def->clock.timers[i]->present == 1) + libxl_defbool_set(&b_info->u.hvm.hpet, 1); + break; + + case VIR_DOMAIN_TIMER_NAME_PLATFORM: + case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: + case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK: Interestingly, and looking at the code [toolstack: tools/libxl/libxl_dom.c:hvm_set_viridian_features(), hypervisor: xen/arch/x86/hvm/viridian.c:update_reference_tsc()] it looks like that to some extent we support the Hyper-V Reference TSC page (Hyper-V Clock?) but it is kept disabled in the viridian base features in libxl. Even if we wanted to enable it would have to be more specific than adding <viridian /> feature like with:
libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_BASE);
I'd think <viridian/> OS feature would enable LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_BASE Yeap.
libxl_bitmap_set(&b_info->u.hvm.viridian_enable, LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_TSC);
And this one would be enabled with
<clock> <timer name='hypervclock'/> </clock>
Is that correct? Should a hypervclock timer also include LIBXL_VIRIDIAN_ENLIGHTENMENT_TIME_REF_COUNT?
IIUC the TIME_REF_COUNT enlightenment is for older versions of windwos, whereas REFERENCE_TSC is the newer one and most performant. Presumably TIME_REF is included in the base viridian features.
and perhaps behind "#ifdef LIBXL_VIRIDIAN_ENLIGHTENMENT_REFERENCE_TSC" as this is only supported since Xen 4.6.0? And I think it would work with tsc_mode not being emulated? Relevant commit on Xen is dd94caca5 ("x86/viridian: add Partition Reference Time enlightenment") Anyhow this is probably not in the context of this series, just food for thought in case we want to have in the future.
Good points, and agree they could be addressed in a followup series that enables viridian enlightenments.
+ case VIR_DOMAIN_TIMER_NAME_RTC: + case VIR_DOMAIN_TIMER_NAME_PIT: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + return -1; + + case VIR_DOMAIN_TIMER_NAME_LAST: + break; } } + Spurious whitespace? Or perhaps it was purposely added?
Initially I think it was spurious, but looking again I think it brings some needed whitespace between these sections of code.
Yeap that's what it sounded like, that is to separate these two sections.
Regards, Jim
b_info->sched_params.weight = 1000; b_info->max_memkb = virDomainDefGetMemoryInitial(def); b_info->target_memkb = def->mem.cur_balloon; @@ -341,12 +369,6 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, libxl_defbool_set(&b_info->u.hvm.acpi, def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_TRISTATE_SWITCH_ON); - for (i = 0; i < def->clock.ntimers; i++) { - if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET && - def->clock.timers[i]->present == 1) { - libxl_defbool_set(&b_info->u.hvm.hpet, 1); - } - }
if (def->nsounds > 0) { /*

While at it, use members of libxl_tsc_mode enum instead of literal int values. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/libxl/libxl_conf.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 3e6d623..b5186f2 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -318,13 +318,16 @@ libxlMakeDomBuildInfo(virDomainDefPtr def, case VIR_DOMAIN_TIMER_NAME_TSC: switch (def->clock.timers[i]->mode) { case VIR_DOMAIN_TIMER_MODE_NATIVE: - b_info->tsc_mode = 2; + b_info->tsc_mode = LIBXL_TSC_MODE_NATIVE; break; case VIR_DOMAIN_TIMER_MODE_PARAVIRT: - b_info->tsc_mode = 3; + b_info->tsc_mode = LIBXL_TSC_MODE_NATIVE_PARAVIRT; + break; + case VIR_DOMAIN_TIMER_MODE_EMULATE: + b_info->tsc_mode = LIBXL_TSC_MODE_ALWAYS_EMULATE; break; default: - b_info->tsc_mode = 1; + b_info->tsc_mode = LIBXL_TSC_MODE_DEFAULT; } break; -- 2.9.2

Currently xenconfig only supports the hpet timer for HVM domains. Include support for tsc timer for both PV and HVM domains. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/xenconfig/xen_common.c | 87 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index 7968d40..ad596d7 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -490,6 +490,7 @@ xenParseCPUFeatures(virConfPtr conf, unsigned long count = 0; const char *str = NULL; int val = 0; + virDomainTimerDefPtr timer; if (xenConfigGetULong(conf, "vcpus", &count, 1) < 0) return -1; @@ -514,6 +515,29 @@ xenParseCPUFeatures(virConfPtr conf, if (str && (virBitmapParse(str, &def->cpumask, 4096) < 0)) return -1; + if (xenConfigGetString(conf, "tsc_mode", &str, NULL) < 0) + return -1; + + if (str) { + if (VIR_EXPAND_N(def->clock.timers, def->clock.ntimers, 1) < 0 || + VIR_ALLOC(timer) < 0) + return -1; + + timer->name = VIR_DOMAIN_TIMER_NAME_TSC; + timer->present = 1; + timer->tickpolicy = -1; + timer->mode = VIR_DOMAIN_TIMER_MODE_AUTO; + timer->track = -1; + if (STREQ_NULLABLE(str, "always_emulate")) + timer->mode = VIR_DOMAIN_TIMER_MODE_EMULATE; + else if (STREQ_NULLABLE(str, "native")) + timer->mode = VIR_DOMAIN_TIMER_MODE_NATIVE; + else if (STREQ_NULLABLE(str, "native_paravirt")) + timer->mode = VIR_DOMAIN_TIMER_MODE_PARAVIRT; + + def->clock.timers[def->clock.ntimers - 1] = timer; + } + if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { if (xenConfigGetBool(conf, "pae", &val, 1) < 0) return -1; @@ -545,9 +569,7 @@ xenParseCPUFeatures(virConfPtr conf, return -1; if (val != -1) { - virDomainTimerDefPtr timer; - - if (VIR_ALLOC_N(def->clock.timers, 1) < 0 || + if (VIR_EXPAND_N(def->clock.timers, def->clock.ntimers, 1) < 0 || VIR_ALLOC(timer) < 0) return -1; @@ -557,8 +579,7 @@ xenParseCPUFeatures(virConfPtr conf, timer->mode = -1; timer->track = -1; - def->clock.ntimers = 1; - def->clock.timers[0] = timer; + def->clock.timers[def->clock.ntimers - 1] = timer; } } @@ -1584,8 +1605,9 @@ static int xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def) { size_t i; + int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM ? 1 : 0; - if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { + if (hvm) { if (xenConfigSetInt(conf, "pae", (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) @@ -1610,12 +1632,57 @@ xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def) (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] == VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) return -1; + } - for (i = 0; i < def->clock.ntimers; i++) { - if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET && - def->clock.timers[i]->present != -1 && - xenConfigSetInt(conf, "hpet", def->clock.timers[i]->present) < 0) + for (i = 0; i < def->clock.ntimers; i++) { + switch ((virDomainTimerNameType) def->clock.timers[i]->name) { + case VIR_DOMAIN_TIMER_NAME_TSC: + switch (def->clock.timers[i]->mode) { + case VIR_DOMAIN_TIMER_MODE_NATIVE: + if (xenConfigSetString(conf, "tsc_mode", "native") < 0) + return -1; + break; + case VIR_DOMAIN_TIMER_MODE_PARAVIRT: + if (xenConfigSetString(conf, "tsc_mode", "native_paravirt") < 0) + return -1; + break; + case VIR_DOMAIN_TIMER_MODE_EMULATE: + if (xenConfigSetString(conf, "tsc_mode", "always_emulate") < 0) + return -1; + break; + default: + if (xenConfigSetString(conf, "tsc_mode", "default") < 0) + return -1; + } + break; + + case VIR_DOMAIN_TIMER_NAME_HPET: + if (hvm) { + int enable_hpet = def->clock.timers[i]->present == 0 ? 0 : 1; + + /* disable hpet if 'present' is 0, enable otherwise */ + if (xenConfigSetInt(conf, "hpet", enable_hpet) < 0) + return -1; + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); return -1; + } + break; + + case VIR_DOMAIN_TIMER_NAME_PLATFORM: + case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: + case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK: + case VIR_DOMAIN_TIMER_NAME_RTC: + case VIR_DOMAIN_TIMER_NAME_PIT: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + return -1; + + case VIR_DOMAIN_TIMER_NAME_LAST: + break; } } -- 2.9.2

Currently xenconfig only supports the hpet timer for HVM domains. Include support for tsc timer for both PV and HVM domains.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/xenconfig/xen_common.c | 87 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 10 deletions(-)
diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index 7968d40..ad596d7 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -490,6 +490,7 @@ xenParseCPUFeatures(virConfPtr conf, unsigned long count = 0; const char *str = NULL; int val = 0; + virDomainTimerDefPtr timer;
if (xenConfigGetULong(conf, "vcpus", &count, 1) < 0) return -1; @@ -514,6 +515,29 @@ xenParseCPUFeatures(virConfPtr conf, if (str && (virBitmapParse(str, &def->cpumask, 4096) < 0)) return -1;
+ if (xenConfigGetString(conf, "tsc_mode", &str, NULL) < 0) + return -1; + + if (str) { + if (VIR_EXPAND_N(def->clock.timers, def->clock.ntimers, 1) < 0 || + VIR_ALLOC(timer) < 0) + return -1; + + timer->name = VIR_DOMAIN_TIMER_NAME_TSC; + timer->present = 1; + timer->tickpolicy = -1; + timer->mode = VIR_DOMAIN_TIMER_MODE_AUTO; + timer->track = -1; + if (STREQ_NULLABLE(str, "always_emulate")) + timer->mode = VIR_DOMAIN_TIMER_MODE_EMULATE; + else if (STREQ_NULLABLE(str, "native")) + timer->mode = VIR_DOMAIN_TIMER_MODE_NATIVE; + else if (STREQ_NULLABLE(str, "native_paravirt")) + timer->mode = VIR_DOMAIN_TIMER_MODE_PARAVIRT; + + def->clock.timers[def->clock.ntimers - 1] = timer; + } + if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { if (xenConfigGetBool(conf, "pae", &val, 1) < 0) return -1; @@ -545,9 +569,7 @@ xenParseCPUFeatures(virConfPtr conf, return -1;
if (val != -1) { - virDomainTimerDefPtr timer; - - if (VIR_ALLOC_N(def->clock.timers, 1) < 0 || + if (VIR_EXPAND_N(def->clock.timers, def->clock.ntimers, 1) < 0 || VIR_ALLOC(timer) < 0) return -1;
@@ -557,8 +579,7 @@ xenParseCPUFeatures(virConfPtr conf, timer->mode = -1; timer->track = -1;
- def->clock.ntimers = 1; - def->clock.timers[0] = timer; + def->clock.timers[def->clock.ntimers - 1] = timer; } }
@@ -1584,8 +1605,9 @@ static int xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def) { size_t i; + int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM ? 1 : 0; You can probably avoid the ternary expression style with turning this into a bool and do !!(def->os.type == VIR_DOMAIN_OSTYPE_HVM) or simply just (def->os.type == VIR_DOMAIN_OSTYPE_HVM). Or is it that libvirt style prefers
On 01/20/2017 01:59 AM, Jim Fehlig wrote: this way? Looking at the file it looks like the style you used above is kept throughout this file.
- if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { + if (hvm) { if (xenConfigSetInt(conf, "pae", (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) @@ -1610,12 +1632,57 @@ xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def) (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] == VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) return -1; + }
- for (i = 0; i < def->clock.ntimers; i++) { - if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET && - def->clock.timers[i]->present != -1 && - xenConfigSetInt(conf, "hpet", def->clock.timers[i]->present) < 0) + for (i = 0; i < def->clock.ntimers; i++) { + switch ((virDomainTimerNameType) def->clock.timers[i]->name) { + case VIR_DOMAIN_TIMER_NAME_TSC: + switch (def->clock.timers[i]->mode) { + case VIR_DOMAIN_TIMER_MODE_NATIVE: + if (xenConfigSetString(conf, "tsc_mode", "native") < 0) + return -1; + break; + case VIR_DOMAIN_TIMER_MODE_PARAVIRT: + if (xenConfigSetString(conf, "tsc_mode", "native_paravirt") < 0) + return -1; + break; + case VIR_DOMAIN_TIMER_MODE_EMULATE: + if (xenConfigSetString(conf, "tsc_mode", "always_emulate") < 0) + return -1; + break; + default: + if (xenConfigSetString(conf, "tsc_mode", "default") < 0) + return -1; + } + break; + + case VIR_DOMAIN_TIMER_NAME_HPET: + if (hvm) { + int enable_hpet = def->clock.timers[i]->present == 0 ? 0 : 1;
Same here i.e. (def->clock.timers[i]->present != 0) ?
+ + /* disable hpet if 'present' is 0, enable otherwise */ + if (xenConfigSetInt(conf, "hpet", enable_hpet) < 0) + return -1; + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); return -1; + } + break; + + case VIR_DOMAIN_TIMER_NAME_PLATFORM: + case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: + case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK: + case VIR_DOMAIN_TIMER_NAME_RTC: + case VIR_DOMAIN_TIMER_NAME_PIT: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + return -1; + + case VIR_DOMAIN_TIMER_NAME_LAST: + break; } }

On 01/20/2017 05:00 AM, Joao Martins wrote:
On 01/20/2017 01:59 AM, Jim Fehlig wrote:
Currently xenconfig only supports the hpet timer for HVM domains. Include support for tsc timer for both PV and HVM domains.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/xenconfig/xen_common.c | 87 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 10 deletions(-)
diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index 7968d40..ad596d7 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -490,6 +490,7 @@ xenParseCPUFeatures(virConfPtr conf, unsigned long count = 0; const char *str = NULL; int val = 0; + virDomainTimerDefPtr timer;
if (xenConfigGetULong(conf, "vcpus", &count, 1) < 0) return -1; @@ -514,6 +515,29 @@ xenParseCPUFeatures(virConfPtr conf, if (str && (virBitmapParse(str, &def->cpumask, 4096) < 0)) return -1;
+ if (xenConfigGetString(conf, "tsc_mode", &str, NULL) < 0) + return -1; + + if (str) { + if (VIR_EXPAND_N(def->clock.timers, def->clock.ntimers, 1) < 0 || + VIR_ALLOC(timer) < 0) + return -1; + + timer->name = VIR_DOMAIN_TIMER_NAME_TSC; + timer->present = 1; + timer->tickpolicy = -1; + timer->mode = VIR_DOMAIN_TIMER_MODE_AUTO; + timer->track = -1; + if (STREQ_NULLABLE(str, "always_emulate")) + timer->mode = VIR_DOMAIN_TIMER_MODE_EMULATE; + else if (STREQ_NULLABLE(str, "native")) + timer->mode = VIR_DOMAIN_TIMER_MODE_NATIVE; + else if (STREQ_NULLABLE(str, "native_paravirt")) + timer->mode = VIR_DOMAIN_TIMER_MODE_PARAVIRT; + + def->clock.timers[def->clock.ntimers - 1] = timer; + } + if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { if (xenConfigGetBool(conf, "pae", &val, 1) < 0) return -1; @@ -545,9 +569,7 @@ xenParseCPUFeatures(virConfPtr conf, return -1;
if (val != -1) { - virDomainTimerDefPtr timer; - - if (VIR_ALLOC_N(def->clock.timers, 1) < 0 || + if (VIR_EXPAND_N(def->clock.timers, def->clock.ntimers, 1) < 0 || VIR_ALLOC(timer) < 0) return -1;
@@ -557,8 +579,7 @@ xenParseCPUFeatures(virConfPtr conf, timer->mode = -1; timer->track = -1;
- def->clock.ntimers = 1; - def->clock.timers[0] = timer; + def->clock.timers[def->clock.ntimers - 1] = timer; } }
@@ -1584,8 +1605,9 @@ static int xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def) { size_t i; + int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM ? 1 : 0; You can probably avoid the ternary expression style with turning this into a bool and do !!(def->os.type == VIR_DOMAIN_OSTYPE_HVM) or simply just (def->os.type == VIR_DOMAIN_OSTYPE_HVM).
I think this is the preferred style.
Or is it that libvirt style prefers this way? Looking at the file it looks like the style you used above is kept throughout this file.
I guess a bad habit was started in this file and grew though copy and past :-).
- if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { + if (hvm) { if (xenConfigSetInt(conf, "pae", (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) @@ -1610,12 +1632,57 @@ xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def) (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] == VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) return -1; + }
- for (i = 0; i < def->clock.ntimers; i++) { - if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET && - def->clock.timers[i]->present != -1 && - xenConfigSetInt(conf, "hpet", def->clock.timers[i]->present) < 0) + for (i = 0; i < def->clock.ntimers; i++) { + switch ((virDomainTimerNameType) def->clock.timers[i]->name) { + case VIR_DOMAIN_TIMER_NAME_TSC: + switch (def->clock.timers[i]->mode) { + case VIR_DOMAIN_TIMER_MODE_NATIVE: + if (xenConfigSetString(conf, "tsc_mode", "native") < 0) + return -1; + break; + case VIR_DOMAIN_TIMER_MODE_PARAVIRT: + if (xenConfigSetString(conf, "tsc_mode", "native_paravirt") < 0) + return -1; + break; + case VIR_DOMAIN_TIMER_MODE_EMULATE: + if (xenConfigSetString(conf, "tsc_mode", "always_emulate") < 0) + return -1; + break; + default: + if (xenConfigSetString(conf, "tsc_mode", "default") < 0) + return -1; + } + break; + + case VIR_DOMAIN_TIMER_NAME_HPET: + if (hvm) { + int enable_hpet = def->clock.timers[i]->present == 0 ? 0 : 1;
Same here i.e. (def->clock.timers[i]->present != 0) ?
Yep. I'll leave this as an int since it is used in xenConfigSetInt.
+ + /* disable hpet if 'present' is 0, enable otherwise */ + if (xenConfigSetInt(conf, "hpet", enable_hpet) < 0) + return -1; + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); return -1; + } + break; + + case VIR_DOMAIN_TIMER_NAME_PLATFORM: + case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: + case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK: + case VIR_DOMAIN_TIMER_NAME_RTC: + case VIR_DOMAIN_TIMER_NAME_PIT: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + return -1; + + case VIR_DOMAIN_TIMER_NAME_LAST: + break; } }
I've squashed the below diff into my branch. Do you have any additional comments on this series? Regards, Jim diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index ad596d7..72ffb30 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -1605,7 +1605,7 @@ static int xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def) { size_t i; - int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM ? 1 : 0; + bool hvm = !!(def->os.type == VIR_DOMAIN_OSTYPE_HVM); if (hvm) { if (xenConfigSetInt(conf, "pae", @@ -1658,7 +1658,7 @@ xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def) case VIR_DOMAIN_TIMER_NAME_HPET: if (hvm) { - int enable_hpet = def->clock.timers[i]->present == 0 ? 0 : 1; + int enable_hpet = def->clock.timers[i]->present != 0; /* disable hpet if 'present' is 0, enable otherwise */ if (xenConfigSetInt(conf, "hpet", enable_hpet) < 0)

On 01/20/2017 10:17 PM, Jim Fehlig wrote:
On 01/20/2017 05:00 AM, Joao Martins wrote:
On 01/20/2017 01:59 AM, Jim Fehlig wrote:
Currently xenconfig only supports the hpet timer for HVM domains. Include support for tsc timer for both PV and HVM domains.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/xenconfig/xen_common.c | 87 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 10 deletions(-)
diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index 7968d40..ad596d7 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -490,6 +490,7 @@ xenParseCPUFeatures(virConfPtr conf, unsigned long count = 0; const char *str = NULL; int val = 0; + virDomainTimerDefPtr timer;
if (xenConfigGetULong(conf, "vcpus", &count, 1) < 0) return -1; @@ -514,6 +515,29 @@ xenParseCPUFeatures(virConfPtr conf, if (str && (virBitmapParse(str, &def->cpumask, 4096) < 0)) return -1;
+ if (xenConfigGetString(conf, "tsc_mode", &str, NULL) < 0) + return -1; + + if (str) { + if (VIR_EXPAND_N(def->clock.timers, def->clock.ntimers, 1) < 0 || + VIR_ALLOC(timer) < 0) + return -1; + + timer->name = VIR_DOMAIN_TIMER_NAME_TSC; + timer->present = 1; + timer->tickpolicy = -1; + timer->mode = VIR_DOMAIN_TIMER_MODE_AUTO; + timer->track = -1; + if (STREQ_NULLABLE(str, "always_emulate")) + timer->mode = VIR_DOMAIN_TIMER_MODE_EMULATE; + else if (STREQ_NULLABLE(str, "native")) + timer->mode = VIR_DOMAIN_TIMER_MODE_NATIVE; + else if (STREQ_NULLABLE(str, "native_paravirt")) + timer->mode = VIR_DOMAIN_TIMER_MODE_PARAVIRT; + + def->clock.timers[def->clock.ntimers - 1] = timer; + } + if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { if (xenConfigGetBool(conf, "pae", &val, 1) < 0) return -1; @@ -545,9 +569,7 @@ xenParseCPUFeatures(virConfPtr conf, return -1;
if (val != -1) { - virDomainTimerDefPtr timer; - - if (VIR_ALLOC_N(def->clock.timers, 1) < 0 || + if (VIR_EXPAND_N(def->clock.timers, def->clock.ntimers, 1) < 0 || VIR_ALLOC(timer) < 0) return -1;
@@ -557,8 +579,7 @@ xenParseCPUFeatures(virConfPtr conf, timer->mode = -1; timer->track = -1;
- def->clock.ntimers = 1; - def->clock.timers[0] = timer; + def->clock.timers[def->clock.ntimers - 1] = timer; } }
@@ -1584,8 +1605,9 @@ static int xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def) { size_t i; + int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM ? 1 : 0; You can probably avoid the ternary expression style with turning this into a bool and do !!(def->os.type == VIR_DOMAIN_OSTYPE_HVM) or simply just (def->os.type == VIR_DOMAIN_OSTYPE_HVM).
I think this is the preferred style.
Or is it that libvirt style prefers this way? Looking at the file it looks like the style you used above is kept throughout this file.
I guess a bad habit was started in this file and grew though copy and past :-). Hehe :)
- if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { + if (hvm) { if (xenConfigSetInt(conf, "pae", (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) @@ -1610,12 +1632,57 @@ xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def) (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] == VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) return -1; + }
- for (i = 0; i < def->clock.ntimers; i++) { - if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET && - def->clock.timers[i]->present != -1 && - xenConfigSetInt(conf, "hpet", def->clock.timers[i]->present) < 0) + for (i = 0; i < def->clock.ntimers; i++) { + switch ((virDomainTimerNameType) def->clock.timers[i]->name) { + case VIR_DOMAIN_TIMER_NAME_TSC: + switch (def->clock.timers[i]->mode) { + case VIR_DOMAIN_TIMER_MODE_NATIVE: + if (xenConfigSetString(conf, "tsc_mode", "native") < 0) + return -1; + break; + case VIR_DOMAIN_TIMER_MODE_PARAVIRT: + if (xenConfigSetString(conf, "tsc_mode", "native_paravirt") < 0) + return -1; + break; + case VIR_DOMAIN_TIMER_MODE_EMULATE: + if (xenConfigSetString(conf, "tsc_mode", "always_emulate") < 0) + return -1; + break; + default: + if (xenConfigSetString(conf, "tsc_mode", "default") < 0) + return -1; + } + break; + + case VIR_DOMAIN_TIMER_NAME_HPET: + if (hvm) { + int enable_hpet = def->clock.timers[i]->present == 0 ? 0 : 1;
Same here i.e. (def->clock.timers[i]->present != 0) ?
Yep. I'll leave this as an int since it is used in xenConfigSetInt.
OK.
+ + /* disable hpet if 'present' is 0, enable otherwise */ + if (xenConfigSetInt(conf, "hpet", enable_hpet) < 0) + return -1; + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); return -1; + } + break; + + case VIR_DOMAIN_TIMER_NAME_PLATFORM: + case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: + case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK: + case VIR_DOMAIN_TIMER_NAME_RTC: + case VIR_DOMAIN_TIMER_NAME_PIT: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + return -1; + + case VIR_DOMAIN_TIMER_NAME_LAST: + break; } }
I've squashed the below diff into my branch. Do you have any additional comments on this series? I haven't spotted any particular issues (e.g. memleaks, test failures) so I have no further comments:
Acked-by: Joao Martins <joao.m.martins@oracle.com>
Regards, Jim
diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index ad596d7..72ffb30 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -1605,7 +1605,7 @@ static int xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def) { size_t i; - int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM ? 1 : 0; + bool hvm = !!(def->os.type == VIR_DOMAIN_OSTYPE_HVM);
if (hvm) { if (xenConfigSetInt(conf, "pae", @@ -1658,7 +1658,7 @@ xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def)
case VIR_DOMAIN_TIMER_NAME_HPET: if (hvm) { - int enable_hpet = def->clock.timers[i]->present == 0 ? 0 : 1; + int enable_hpet = def->clock.timers[i]->present != 0;
/* disable hpet if 'present' is 0, enable otherwise */ if (xenConfigSetInt(conf, "hpet", enable_hpet) < 0)

On 01/20/2017 04:16 PM, Joao Martins wrote:
On 01/20/2017 10:17 PM, Jim Fehlig wrote:
On 01/20/2017 05:00 AM, Joao Martins wrote:
On 01/20/2017 01:59 AM, Jim Fehlig wrote:
Currently xenconfig only supports the hpet timer for HVM domains. Include support for tsc timer for both PV and HVM domains.
Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/xenconfig/xen_common.c | 87 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 10 deletions(-)
diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index 7968d40..ad596d7 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -490,6 +490,7 @@ xenParseCPUFeatures(virConfPtr conf, unsigned long count = 0; const char *str = NULL; int val = 0; + virDomainTimerDefPtr timer;
if (xenConfigGetULong(conf, "vcpus", &count, 1) < 0) return -1; @@ -514,6 +515,29 @@ xenParseCPUFeatures(virConfPtr conf, if (str && (virBitmapParse(str, &def->cpumask, 4096) < 0)) return -1;
+ if (xenConfigGetString(conf, "tsc_mode", &str, NULL) < 0) + return -1; + + if (str) { + if (VIR_EXPAND_N(def->clock.timers, def->clock.ntimers, 1) < 0 || + VIR_ALLOC(timer) < 0) + return -1; + + timer->name = VIR_DOMAIN_TIMER_NAME_TSC; + timer->present = 1; + timer->tickpolicy = -1; + timer->mode = VIR_DOMAIN_TIMER_MODE_AUTO; + timer->track = -1; + if (STREQ_NULLABLE(str, "always_emulate")) + timer->mode = VIR_DOMAIN_TIMER_MODE_EMULATE; + else if (STREQ_NULLABLE(str, "native")) + timer->mode = VIR_DOMAIN_TIMER_MODE_NATIVE; + else if (STREQ_NULLABLE(str, "native_paravirt")) + timer->mode = VIR_DOMAIN_TIMER_MODE_PARAVIRT; + + def->clock.timers[def->clock.ntimers - 1] = timer; + } + if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { if (xenConfigGetBool(conf, "pae", &val, 1) < 0) return -1; @@ -545,9 +569,7 @@ xenParseCPUFeatures(virConfPtr conf, return -1;
if (val != -1) { - virDomainTimerDefPtr timer; - - if (VIR_ALLOC_N(def->clock.timers, 1) < 0 || + if (VIR_EXPAND_N(def->clock.timers, def->clock.ntimers, 1) < 0 || VIR_ALLOC(timer) < 0) return -1;
@@ -557,8 +579,7 @@ xenParseCPUFeatures(virConfPtr conf, timer->mode = -1; timer->track = -1;
- def->clock.ntimers = 1; - def->clock.timers[0] = timer; + def->clock.timers[def->clock.ntimers - 1] = timer; } }
@@ -1584,8 +1605,9 @@ static int xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def) { size_t i; + int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM ? 1 : 0; You can probably avoid the ternary expression style with turning this into a bool and do !!(def->os.type == VIR_DOMAIN_OSTYPE_HVM) or simply just (def->os.type == VIR_DOMAIN_OSTYPE_HVM).
I think this is the preferred style.
Or is it that libvirt style prefers this way? Looking at the file it looks like the style you used above is kept throughout this file.
I guess a bad habit was started in this file and grew though copy and past :-). Hehe :)
- if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { + if (hvm) { if (xenConfigSetInt(conf, "pae", (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) @@ -1610,12 +1632,57 @@ xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def) (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] == VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) return -1; + }
- for (i = 0; i < def->clock.ntimers; i++) { - if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET && - def->clock.timers[i]->present != -1 && - xenConfigSetInt(conf, "hpet", def->clock.timers[i]->present) < 0) + for (i = 0; i < def->clock.ntimers; i++) { + switch ((virDomainTimerNameType) def->clock.timers[i]->name) { + case VIR_DOMAIN_TIMER_NAME_TSC: + switch (def->clock.timers[i]->mode) { + case VIR_DOMAIN_TIMER_MODE_NATIVE: + if (xenConfigSetString(conf, "tsc_mode", "native") < 0) + return -1; + break; + case VIR_DOMAIN_TIMER_MODE_PARAVIRT: + if (xenConfigSetString(conf, "tsc_mode", "native_paravirt") < 0) + return -1; + break; + case VIR_DOMAIN_TIMER_MODE_EMULATE: + if (xenConfigSetString(conf, "tsc_mode", "always_emulate") < 0) + return -1; + break; + default: + if (xenConfigSetString(conf, "tsc_mode", "default") < 0) + return -1; + } + break; + + case VIR_DOMAIN_TIMER_NAME_HPET: + if (hvm) { + int enable_hpet = def->clock.timers[i]->present == 0 ? 0 : 1;
Same here i.e. (def->clock.timers[i]->present != 0) ?
Yep. I'll leave this as an int since it is used in xenConfigSetInt.
OK.
+ + /* disable hpet if 'present' is 0, enable otherwise */ + if (xenConfigSetInt(conf, "hpet", enable_hpet) < 0) + return -1; + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); return -1; + } + break; + + case VIR_DOMAIN_TIMER_NAME_PLATFORM: + case VIR_DOMAIN_TIMER_NAME_KVMCLOCK: + case VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK: + case VIR_DOMAIN_TIMER_NAME_RTC: + case VIR_DOMAIN_TIMER_NAME_PIT: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported timer type (name) '%s'"), + virDomainTimerNameTypeToString(def->clock.timers[i]->name)); + return -1; + + case VIR_DOMAIN_TIMER_NAME_LAST: + break; } }
I've squashed the below diff into my branch. Do you have any additional comments on this series? I haven't spotted any particular issues (e.g. memleaks, test failures) so I have no further comments:
Acked-by: Joao Martins <joao.m.martins@oracle.com>
Thanks! I've pushed the series now. Regards, Jim

Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- tests/xlconfigdata/test-fullvirt-hpet-timer.cfg | 27 ++++++++++ tests/xlconfigdata/test-fullvirt-hpet-timer.xml | 64 +++++++++++++++++++++++ tests/xlconfigdata/test-fullvirt-multi-timer.cfg | 28 ++++++++++ tests/xlconfigdata/test-fullvirt-multi-timer.xml | 65 ++++++++++++++++++++++++ tests/xlconfigdata/test-fullvirt-tsc-timer.cfg | 27 ++++++++++ tests/xlconfigdata/test-fullvirt-tsc-timer.xml | 64 +++++++++++++++++++++++ tests/xlconfigtest.c | 3 ++ 7 files changed, 278 insertions(+) diff --git a/tests/xlconfigdata/test-fullvirt-hpet-timer.cfg b/tests/xlconfigdata/test-fullvirt-hpet-timer.cfg new file mode 100644 index 0000000..a566bd7 --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-hpet-timer.cfg @@ -0,0 +1,27 @@ +name = "XenGuest2" +uuid = "c7a5fdb2-cdaf-9455-926a-d65c16db1809" +maxmem = 579 +memory = 394 +vcpus = 1 +pae = 1 +acpi = 1 +apic = 1 +hap = 0 +viridian = 0 +hpet = 1 +rtc_timeoffset = 0 +localtime = 0 +on_poweroff = "destroy" +on_reboot = "restart" +on_crash = "restart" +device_model = "/usr/lib/xen/bin/qemu-system-i386" +sdl = 0 +vnc = 1 +vncunused = 1 +vnclisten = "127.0.0.1" +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,model=e1000,rate=10240KB/s" ] +parallel = "none" +serial = "none" +builder = "hvm" +boot = "d" +disk = [ "format=raw,vdev=hda,access=rw,backendtype=phy,target=/dev/HostVG/XenGuest2", "format=qcow2,vdev=hdb,access=rw,backendtype=qdisk,target=/var/lib/libvirt/images/XenGuest2-home", "format=raw,vdev=hdc,access=ro,backendtype=qdisk,devtype=cdrom,target=/root/boot.iso" ] diff --git a/tests/xlconfigdata/test-fullvirt-hpet-timer.xml b/tests/xlconfigdata/test-fullvirt-hpet-timer.xml new file mode 100644 index 0000000..e3d2c4c --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-hpet-timer.xml @@ -0,0 +1,64 @@ +<domain type='xen'> + <name>XenGuest2</name> + <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>592896</memory> + <currentMemory unit='KiB'>403456</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> + <boot dev='cdrom'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + <hap state='off'/> + </features> + <clock offset='variable' adjustment='0' basis='utc'> + <timer name='hpet' present='yes'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> + <disk type='block' device='disk'> + <driver name='phy' type='raw'/> + <source dev='/dev/HostVG/XenGuest2'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2'/> + <source file='/var/lib/libvirt/images/XenGuest2-home'/> + <target dev='hdb' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='1'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/root/boot.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + <address type='drive' controller='0' bus='1' target='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <interface type='bridge'> + <mac address='00:16:3e:66:92:9c'/> + <source bridge='xenbr1'/> + <bandwidth> + <outbound average='10240'/> + </bandwidth> + <script path='vif-bridge'/> + <model type='e1000'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <video> + <model type='cirrus' vram='8192' heads='1' primary='yes'/> + </video> + </devices> +</domain> diff --git a/tests/xlconfigdata/test-fullvirt-multi-timer.cfg b/tests/xlconfigdata/test-fullvirt-multi-timer.cfg new file mode 100644 index 0000000..5a78585 --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-multi-timer.cfg @@ -0,0 +1,28 @@ +name = "XenGuest2" +uuid = "c7a5fdb2-cdaf-9455-926a-d65c16db1809" +maxmem = 579 +memory = 394 +vcpus = 1 +pae = 1 +acpi = 1 +apic = 1 +hap = 0 +viridian = 0 +tsc_mode = "native" +hpet = 1 +rtc_timeoffset = 0 +localtime = 0 +on_poweroff = "destroy" +on_reboot = "restart" +on_crash = "restart" +device_model = "/usr/lib/xen/bin/qemu-system-i386" +sdl = 0 +vnc = 1 +vncunused = 1 +vnclisten = "127.0.0.1" +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,model=e1000,rate=10240KB/s" ] +parallel = "none" +serial = "none" +builder = "hvm" +boot = "d" +disk = [ "format=raw,vdev=hda,access=rw,backendtype=phy,target=/dev/HostVG/XenGuest2", "format=qcow2,vdev=hdb,access=rw,backendtype=qdisk,target=/var/lib/libvirt/images/XenGuest2-home", "format=raw,vdev=hdc,access=ro,backendtype=qdisk,devtype=cdrom,target=/root/boot.iso" ] diff --git a/tests/xlconfigdata/test-fullvirt-multi-timer.xml b/tests/xlconfigdata/test-fullvirt-multi-timer.xml new file mode 100644 index 0000000..3e7c68c --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-multi-timer.xml @@ -0,0 +1,65 @@ +<domain type='xen'> + <name>XenGuest2</name> + <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>592896</memory> + <currentMemory unit='KiB'>403456</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> + <boot dev='cdrom'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + <hap state='off'/> + </features> + <clock offset='variable' adjustment='0' basis='utc'> + <timer name='tsc' present='yes' mode='native'/> + <timer name='hpet' present='yes'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> + <disk type='block' device='disk'> + <driver name='phy' type='raw'/> + <source dev='/dev/HostVG/XenGuest2'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2'/> + <source file='/var/lib/libvirt/images/XenGuest2-home'/> + <target dev='hdb' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='1'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/root/boot.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + <address type='drive' controller='0' bus='1' target='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <interface type='bridge'> + <mac address='00:16:3e:66:92:9c'/> + <source bridge='xenbr1'/> + <bandwidth> + <outbound average='10240'/> + </bandwidth> + <script path='vif-bridge'/> + <model type='e1000'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <video> + <model type='cirrus' vram='8192' heads='1' primary='yes'/> + </video> + </devices> +</domain> diff --git a/tests/xlconfigdata/test-fullvirt-tsc-timer.cfg b/tests/xlconfigdata/test-fullvirt-tsc-timer.cfg new file mode 100644 index 0000000..609c0fd --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-tsc-timer.cfg @@ -0,0 +1,27 @@ +name = "XenGuest2" +uuid = "c7a5fdb2-cdaf-9455-926a-d65c16db1809" +maxmem = 579 +memory = 394 +vcpus = 1 +pae = 1 +acpi = 1 +apic = 1 +hap = 0 +viridian = 0 +tsc_mode = "native" +rtc_timeoffset = 0 +localtime = 0 +on_poweroff = "destroy" +on_reboot = "restart" +on_crash = "restart" +device_model = "/usr/lib/xen/bin/qemu-system-i386" +sdl = 0 +vnc = 1 +vncunused = 1 +vnclisten = "127.0.0.1" +vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,model=e1000,rate=10240KB/s" ] +parallel = "none" +serial = "none" +builder = "hvm" +boot = "d" +disk = [ "format=raw,vdev=hda,access=rw,backendtype=phy,target=/dev/HostVG/XenGuest2", "format=qcow2,vdev=hdb,access=rw,backendtype=qdisk,target=/var/lib/libvirt/images/XenGuest2-home", "format=raw,vdev=hdc,access=ro,backendtype=qdisk,devtype=cdrom,target=/root/boot.iso" ] diff --git a/tests/xlconfigdata/test-fullvirt-tsc-timer.xml b/tests/xlconfigdata/test-fullvirt-tsc-timer.xml new file mode 100644 index 0000000..bedbe8e --- /dev/null +++ b/tests/xlconfigdata/test-fullvirt-tsc-timer.xml @@ -0,0 +1,64 @@ +<domain type='xen'> + <name>XenGuest2</name> + <uuid>c7a5fdb2-cdaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>592896</memory> + <currentMemory unit='KiB'>403456</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='xenfv'>hvm</type> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> + <boot dev='cdrom'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + <hap state='off'/> + </features> + <clock offset='variable' adjustment='0' basis='utc'> + <timer name='tsc' present='yes' mode='native'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator> + <disk type='block' device='disk'> + <driver name='phy' type='raw'/> + <source dev='/dev/HostVG/XenGuest2'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2'/> + <source file='/var/lib/libvirt/images/XenGuest2-home'/> + <target dev='hdb' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='1'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/root/boot.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + <address type='drive' controller='0' bus='1' target='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <interface type='bridge'> + <mac address='00:16:3e:66:92:9c'/> + <source bridge='xenbr1'/> + <bandwidth> + <outbound average='10240'/> + </bandwidth> + <script path='vif-bridge'/> + <model type='e1000'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <video> + <model type='cirrus' vram='8192' heads='1' primary='yes'/> + </video> + </devices> +</domain> diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c index cab0c0d..e74e4d6 100644 --- a/tests/xlconfigtest.c +++ b/tests/xlconfigtest.c @@ -265,6 +265,9 @@ mymain(void) DO_TEST("spice-features"); DO_TEST("vif-rate"); DO_TEST("fullvirt-nohap"); + DO_TEST("fullvirt-hpet-timer"); + DO_TEST("fullvirt-tsc-timer"); + DO_TEST("fullvirt-multi-timer"); DO_TEST("paravirt-cmdline"); DO_TEST_FORMAT("paravirt-cmdline-extra-root", false); -- 2.9.2
participants (2)
-
Jim Fehlig
-
Joao Martins