On 2/12/26 15:21, Peter Krempa wrote:
> On Wed, Feb 11, 2026 at 12:50:24 +0100, Michal Privoznik via Devel wrote:
>> From: Michal Privoznik <[email protected]>
>>
>> Since some hyperv features might be already enabled/disabled when
>> entering qemuProcessEnableDomainFeatures() only those which are
>> not set in domain XML (i.e. are VIR_TRISTATE_SWITCH_ABSENT)
>> should be modified. Furthermore, some features are not a simple
>> on/off switch, but a number or a string even. Well, that doesn't
>> matter really as the logic for setting them is the same: only set
>> their value iff they are not already set.
>>
>> Resolves: https://issues.redhat.com/browse/RHEL-148219
>> Signed-off-by: Michal Privoznik <[email protected]>
>> ---
>>  src/qemu/qemu_process.c                       | 24 ++++++++++++-------
>>  .../hyperv-host-model.x86_64-latest.args      |  2 +-
>>  2 files changed, 17 insertions(+), 9 deletions(-)
>>
>> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
>> index c5b2a5fda8..27aa1896d4 100644
>> --- a/src/qemu/qemu_process.c
>> +++ b/src/qemu/qemu_process.c
>> @@ -6960,30 +6960,38 @@ qemuProcessEnableDomainFeatures(virDomainObj *vm)
>>      }
>>  
>>      for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) {
>> +        virTristateSwitch origState = vm->def->hyperv.features[i];
>> +
>>          if (!VIR_DOMAIN_CAPS_ENUM_IS_SET(hv->features, i))
>>              continue;
>>  
>> -        vm->def->hyperv.features[i] = VIR_TRISTATE_SWITCH_ON;
>> +        if (vm->def->hyperv.features[i] == VIR_TRISTATE_SWITCH_ABSENT)
>> +            vm->def->hyperv.features[i] = VIR_TRISTATE_SWITCH_ON;
> 
> 
> [...]
> 
> 
>>  
>>          if (i == VIR_DOMAIN_HYPERV_SPINLOCKS) {
>>              if (hv->spinlocks != 0) {
>> -                vm->def->hyperv.spinlocks = hv->spinlocks;
>> +                if (vm->def->hyperv.spinlocks == 0)
>> +                    vm->def->hyperv.spinlocks = hv->spinlocks;
> 
> 
> This feature is parsed as:
> 
> 
>         case VIR_DOMAIN_HYPERV_SPINLOCKS:
>             if (value != VIR_TRISTATE_SWITCH_ON)
>                 break;
> 
>             if (virXMLPropUIntDefault(node, "retries", 0, VIR_XML_PROP_NONE,
>                                       &def->hyperv.spinlocks, UINT_MAX) < 0) {
>                 return -1;
>             }
> 
>             if (def->hyperv.spinlocks < 0xFFF) {
>                 virReportError(VIR_ERR_XML_ERROR, "%s",
>                                _("HyperV spinlock retry count must be at 
> least 4095"));
>                 return -1;
>             }
> 
> Thus the value will never be 0 if it was enabled in the XML. Practically
> though I don't think it matters because the user in such case set what
> they wanted.
> 
> To make it more obvious that this would happen I'd probably skip the
> attempt to set anything if origState of this feature is not _ABSENT.
> 
> In fact IMO none of the settings should be auto-filled if the user
> provided config of the feature.

Ah good point. All I wanted was to fill in other values for particular
enlightenment.

> 
> 
>>              } else {
>> -                vm->def->hyperv.features[i] = VIR_TRISTATE_SWITCH_ABSENT;
>> +                vm->def->hyperv.features[i] = origState;
>>              }
>>          } else if (i == VIR_DOMAIN_HYPERV_STIMER) {
>> -            vm->def->hyperv.stimer_direct = hv->stimer_direct;
>> +            if (vm->def->hyperv.stimer_direct == VIR_TRISTATE_SWITCH_ABSENT)
>> +                vm->def->hyperv.stimer_direct = hv->stimer_direct;
>>              /* Both hv-stimer and hv-stimer-direct require hv-time which is
>>               * expose as a timer. Enable it. */
>>              qemuProcessMaybeAddHypervTimer(vm->def);
>>          } else if (i == VIR_DOMAIN_HYPERV_TLBFLUSH) {
>> -            vm->def->hyperv.tlbflush_direct = hv->tlbflush_direct;
>> -            vm->def->hyperv.tlbflush_extended = hv->tlbflush_extended;
>> +            if (vm->def->hyperv.tlbflush_direct == 
>> VIR_TRISTATE_SWITCH_ABSENT)
>> +                vm->def->hyperv.tlbflush_direct = hv->tlbflush_direct;
>> +            if (vm->def->hyperv.tlbflush_extended == 
>> VIR_TRISTATE_SWITCH_ABSENT)
>> +                vm->def->hyperv.tlbflush_extended = hv->tlbflush_extended;
>>          } else if (i == VIR_DOMAIN_HYPERV_VENDOR_ID) {
>>              if (hv->vendor_id) {
>> -                vm->def->hyperv.vendor_id = g_strdup(hv->vendor_id);
>> +                if (!vm->def->hyperv.vendor_id)
>> +                    vm->def->hyperv.vendor_id = g_strdup(hv->vendor_id);
> 
> e.g. this feature can't exist without having the 'value' field populated
> by the user.
> 
> So [1] could then be:
> 
> 
>         if (vm->def->hyperv.features[i] == VIR_TRISTATE_SWITCH_ABSENT) {
>             vm->def->hyperv.features[i] = VIR_TRISTATE_SWITCH_ON;
>         } else {
>             /* if the user provided already config for this we skip the
>              * auto-population code */
>              continue;
>         }
> 
> and the rest would then require no change at all.
> 

Funny, this was my first iteration I had locally. Consider this squashed
in, locally.

Michal

Reply via email to