[libvirt] [PATCHv2 11/11] qemu_driver: BaselineHypervisorCPU supports S390 using QEMU/QMP

Collin Walling walling at linux.ibm.com
Tue Jul 17 22:39:47 UTC 2018


On 07/17/2018 05:01 PM, David Hildenbrand wrote:
> On 13.07.2018 18:00, Jiri Denemark wrote:
>> On Mon, Jul 09, 2018 at 22:56:55 -0500, Chris Venteicher wrote:
>>> Transient S390 configurations require using QEMU to compute CPU Model
>>> Baseline and to do CPU Feature Expansion.
>>>
>>> Start and use a single QEMU instance to do both the baseline and
>>> expansion transactions required by BaselineHypervisorCPU.
>>>
>>> CPU Feature Expansion uses true / false to indicate if property is/isn't
>>> included in model. Baseline only returns property list where all
>>> enumerated properties are included.
>>
>> So are you saying on s390 there's no chance there would be a CPU model
>> with some feature which is included in the CPU model disabled for some
>> reason? Sounds too good to be true :-) (This is the question I referred
>> to in one of my replies to the other patches.)
> 
> Giving some background information: When we expand/baseline CPU models,
> we always expand them to the "-base" variants of our CPU models, which
> contain some set of features we expect to be around in all sane
> configurations ("minimal feature set").
> 
> It is very unlikely that we ever have something like
> "z14-base,featx=off", but it could happen
>  - When using an emulator (TCG)
>  - When running nested and the guest hypervisor is started with such a
>    strange CPU model
>  - When something in the HW is very wrong or eventually removed in the
>    future (unlikely but possible)
> 
> On some very weird inputs to a baseline request, such a strange model
> can also be the result. But it is very unusual.
> 
> I assume something like "baseline z14-base,featx=off with z14-base" will
> result in "z14-base,featx=off", too.
> 
> 

That's correct. A CPU model with a feature disabled that is baseline with a CPU 
model with that same feature enabled will omit that feature in the QMP response.

e.g. if z14-base has features x, y, z then

"baseline z14-base,featx=off with z14-base" will result in "z14-base,featy=on,featz=on"

Since baseline will just report a base cpu and its minimal feature set... I wonder if it
makes sense for libvirt to just report the features resulting from the baseline command 
instead of later calling expansion?

>>
>> Most of the code you added in this patch is indented by three spaces
>> while we use four spaces in libvirt.
>>
>>> ---
>>>  src/qemu/qemu_driver.c | 74 +++++++++++++++++++++++++++++++++++++-----
>>>  1 file changed, 65 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
>>> index 9a35e04a85..6c6107f077 100644
>>> --- a/src/qemu/qemu_driver.c
>>> +++ b/src/qemu/qemu_driver.c
>>> @@ -13400,10 +13400,13 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
>>>      virArch arch;
>>>      virDomainVirtType virttype;
>>>      virDomainCapsCPUModelsPtr cpuModels;
>>> -    bool migratable;
>>> +    bool migratable_only;
>>
>> Why? The bool says the user specified
>> VIR_CONNECT_BASELINE_CPU_MIGRATABLE which means they want a migratable
>> CPU back. What does the "_only" part mean? This API does not return
>> several CPUs, it only returns a single one and it's either migratable or
>> not.
>>
>>>      virCPUDefPtr cpu = NULL;
>>>      char *cpustr = NULL;
>>>      char **features = NULL;
>>> +    virQEMUCapsInitQMPCommandPtr cmd = NULL;
>>> +    bool forceTCG = false;
>>> +    qemuMonitorCPUModelInfoPtr modelInfo = NULL;
>>>  
>>>      virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES |
>>>                    VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL);
>>> @@ -13411,8 +13414,6 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
>>>      if (virConnectBaselineHypervisorCPUEnsureACL(conn) < 0)
>>>          goto cleanup;
>>>  
>>> -    migratable = !!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE);
>>> -
>>>      if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_AUTO)))
>>>          goto cleanup;
>>>  
>>> @@ -13425,6 +13426,19 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
>>>      if (!qemuCaps)
>>>          goto cleanup;
>>>  
>>> +    /* QEMU can enumerate non-migratable cpu model features for some archs like x86
>>> +     * migratable_only == true:  ask for and include only migratable features
>>> +     * migratable_only == false: ask for and include all features
>>> +     */
>>> +    migratable_only = !!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE);
>>> +
>>> +    if (ARCH_IS_S390(arch)) {
>>> +       /* QEMU for S390 arch only enumerates migratable features
>>> +        * No reason to explicitly ask QEMU for or include non-migratable features
>>> +        */
>>> +       migratable_only = true;
>>> +    }
>>> +
>>
>> And what if they come up with some features which are not migratable in
>> the future? I don't think there's any reason for this API to mess with
>> the value. The code should just provide the same CPU in both cases for
>> s390.
> 
> s390x usually only provides features if they are migratable. Could it
> happen it the future that we have something that cannot be migrated?
> Possible but very very unlikely. We cared about migration (even for
> nested support) right from the beginning. As of now, we have no features
> that are supported by QEMU that cannot be migrated - in contrast to e.g.
> x86 (e.g. VMX/SVM). Every new feature has to be whitelisted in QEMU -
> and we only allow to do so if migration is in place for it.
> 

You're a gold mine on this kind of information.  I may have to pester you about some 
CPU model related stuff in the future :)

>>
>>>      if (!(cpuModels = virQEMUCapsGetCPUDefinitions(qemuCaps, virttype)) ||
>>>          cpuModels->nmodels == 0) {
>>>          virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
>>> @@ -13437,18 +13451,31 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
>>>  
>>>      if (ARCH_IS_X86(arch)) {
>>>          int rc = virQEMUCapsGetCPUFeatures(qemuCaps, virttype,
>>> -                                           migratable, &features);
>>> +                                           migratable_only, &features);
>>>          if (rc < 0)
>>>              goto cleanup;
>>>          if (features && rc == 0) {
>>>              /* We got only migratable features from QEMU if we asked for them,
>>>               * no further filtering in virCPUBaseline is desired. */
>>> -            migratable = false;
>>> +            migratable_only = false;
>>>          }
>>>  
>>>          if (!(cpu = virCPUBaseline(arch, cpus, ncpus, cpuModels,
>>> -                                   (const char **)features, migratable)))
>>> +                                   (const char **)features, migratable_only)))
>>>              goto cleanup;
>>> +    } else if (ARCH_IS_S390(arch)) {
>>> +
>>
>> No need for this extra empty line.
>>
>>> +       const char *binary = virQEMUCapsGetBinary(qemuCaps);
>>> +       virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
>>> +
>>> +       if (!(cmd = virQEMUCapsNewQMPCommandConnection(binary, cfg->libDir,
>>> +                                                      cfg->user, cfg->group,
>>> +                                                      forceTCG)))
>>> +          goto cleanup;
>>> +
>>> +       if ((virQEMUCapsQMPBaselineCPUModel(cmd, cpus, &cpu) < 0) || !cpu)
>>
>> Hmm, I think you should only call this when the user passed more than
>> one CPU. This API is expected to work even with a single CPU in which
>> case it just expands it if the corresponding flag was set.
> 
> The QEMU side will bail out if only one model is passed, so this sounds
> like the right thing to do.
> 
>>
>>> +          goto cleanup; /* Content Error */
>>
>> What did you want to say with the comment? I think you can safely drop
>> it.
>>
>>> +
>>
>> And this one either.
>>
>>>      } else {
>>>          virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
>>>                         _("computing baseline hypervisor CPU is not supported "
>>> @@ -13458,9 +13485,36 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn,
>>>  
>>>      cpu->fallback = VIR_CPU_FALLBACK_FORBID;
>>>  
>>> -    if ((flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) &&
>>> -        virCPUExpandFeatures(arch, cpu) < 0)
>>> -        goto cleanup;
>>> +    if (flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) {
>>> +       if (ARCH_IS_X86(arch)) {
>>> +          if (virCPUExpandFeatures(arch, cpu) < 0)
>>> +             goto cleanup;
>>> +       } else if (ARCH_IS_S390(arch)) {
>>> +
>>
>> Extra empty line.
>>
>>> +          if (!(modelInfo = virQEMUCapsCPUModelInfoFromCPUDef(cpu)))
>>> +             goto cleanup;
>>> +
>>> +          virCPUDefFree(cpu); /* Null on failure, repopulated on success */
>>
>> I think it would be better to drop the comment and just do it:
>>
>>              cpu = NULL;
>>
>> Oh and since this goes from CPUDef to modelInfo and back, you may
>> actually need to do some extra work to persist some parts of the
>> original CPU definitions which get lost during the translation (e.g.,
>> the CPU vendor) if it's applicable for s390. We have to do similar stuff
>> for x86 too when we translate CPUDef into CPUID bits and back.
> 
> My assumption is that there are not such things (e.g. like vendor).
> 

Correct. AFAIK and from what I've seen, s390 only cares about the arch, model, and
features data with regards to cpu models and libvirt.

-- 
Respectfully,
- Collin Walling




More information about the libvir-list mailing list