cpu.c 23.6 KB
Newer Older
J
Jiri Denemark 已提交
1 2 3
/*
 * cpu.c: internal functions for CPU manipulation
 *
4
 * Copyright (C) 2009-2013 Red Hat, Inc.
J
Jiri Denemark 已提交
5 6 7 8 9 10 11 12 13 14 15 16
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library.  If not, see
O
Osier Yang 已提交
18
 * <http://www.gnu.org/licenses/>.
J
Jiri Denemark 已提交
19 20 21 22 23 24 25
 *
 * Authors:
 *      Jiri Denemark <jdenemar@redhat.com>
 */

#include <config.h>

26
#include "virlog.h"
27
#include "viralloc.h"
28
#include "virxml.h"
J
Jiri Denemark 已提交
29
#include "cpu.h"
30
#include "cpu_map.h"
J
Jiri Denemark 已提交
31
#include "cpu_x86.h"
32
#include "cpu_ppc64.h"
T
Thang Pham 已提交
33
#include "cpu_s390.h"
C
Chuck Short 已提交
34
#include "cpu_arm.h"
35
#include "util/virstring.h"
J
Jiri Denemark 已提交
36 37 38 39


#define VIR_FROM_THIS VIR_FROM_CPU

40 41
VIR_LOG_INIT("cpu.cpu");

J
Jiri Denemark 已提交
42 43
static struct cpuArchDriver *drivers[] = {
    &cpuDriverX86,
44
    &cpuDriverPPC64,
T
Thang Pham 已提交
45
    &cpuDriverS390,
C
Chuck Short 已提交
46
    &cpuDriverArm,
J
Jiri Denemark 已提交
47 48 49 50
};


static struct cpuArchDriver *
51
cpuGetSubDriver(virArch arch)
J
Jiri Denemark 已提交
52
{
53 54
    size_t i;
    size_t j;
J
Jiri Denemark 已提交
55

56
    if (arch == VIR_ARCH_NONE) {
57 58
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("undefined hardware architecture"));
J
Jiri Denemark 已提交
59 60 61
        return NULL;
    }

J
Jiri Denemark 已提交
62
    for (i = 0; i < ARRAY_CARDINALITY(drivers); i++) {
J
Jiri Denemark 已提交
63
        for (j = 0; j < drivers[i]->narch; j++) {
64
            if (arch == drivers[i]->arch[j])
J
Jiri Denemark 已提交
65 66 67 68
                return drivers[i];
        }
    }

J
Jiri Denemark 已提交
69 70 71 72
    virReportError(VIR_ERR_NO_SUPPORT,
                   _("'%s' architecture is not supported by CPU driver"),
                   virArchToString(arch));
    return NULL;
J
Jiri Denemark 已提交
73 74 75
}


76 77 78 79 80
static struct cpuArchDriver *
cpuGetSubDriverByName(const char *name)
{
    size_t i;

J
Jiri Denemark 已提交
81
    for (i = 0; i < ARRAY_CARDINALITY(drivers); i++) {
82 83 84 85 86 87 88 89 90 91 92
        if (STREQ_NULLABLE(name, drivers[i]->name))
            return drivers[i];
    }

    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("CPU driver '%s' does not exist"),
                   name);
    return NULL;
}


93 94 95 96 97 98 99 100 101 102 103 104 105
/**
 * cpuCompareXML:
 *
 * @host: host CPU definition
 * @xml: XML description of either guest or host CPU to be compared with @host
 *
 * Compares the CPU described by @xml with @host CPU.
 *
 * Returns VIR_CPU_COMPARE_ERROR on error, VIR_CPU_COMPARE_INCOMPATIBLE when
 * the two CPUs are incompatible, VIR_CPU_COMPARE_IDENTICAL when the two CPUs
 * are identical, VIR_CPU_COMPARE_SUPERSET when the @xml CPU is a superset of
 * the @host CPU.
 */
J
Jiri Denemark 已提交
106
virCPUCompareResult
107
cpuCompareXML(virCPUDefPtr host,
108 109
              const char *xml,
              bool failIncompatible)
J
Jiri Denemark 已提交
110 111 112 113 114 115
{
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
    virCPUDefPtr cpu = NULL;
    virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR;

116 117
    VIR_DEBUG("host=%p, xml=%s", host, NULLSTR(xml));

118
    if (!(doc = virXMLParseStringCtxt(xml, _("(CPU_definition)"), &ctxt)))
119
        goto cleanup;
J
Jiri Denemark 已提交
120

121
    cpu = virCPUDefParseXML(ctxt->node, ctxt, VIR_CPU_TYPE_AUTO);
J
Jiri Denemark 已提交
122 123 124
    if (cpu == NULL)
        goto cleanup;

125
    ret = cpuCompare(host, cpu, failIncompatible);
J
Jiri Denemark 已提交
126

127
 cleanup:
J
Jiri Denemark 已提交
128 129 130 131 132 133 134 135
    virCPUDefFree(cpu);
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);

    return ret;
}


136 137 138 139 140 141 142 143 144 145 146 147 148
/**
 * cpuCompare:
 *
 * @host: host CPU definition
 * @cpu: either guest or host CPU to be compared with @host
 *
 * Compares the CPU described by @cpu with @host CPU.
 *
 * Returns VIR_CPU_COMPARE_ERROR on error, VIR_CPU_COMPARE_INCOMPATIBLE when
 * the two CPUs are incompatible, VIR_CPU_COMPARE_IDENTICAL when the two CPUs
 * are identical, VIR_CPU_COMPARE_SUPERSET when the @cpu CPU is a superset of
 * the @host CPU.
 */
J
Jiri Denemark 已提交
149
virCPUCompareResult
150
cpuCompare(virCPUDefPtr host,
151 152
           virCPUDefPtr cpu,
           bool failIncompatible)
J
Jiri Denemark 已提交
153 154 155
{
    struct cpuArchDriver *driver;

156 157
    VIR_DEBUG("host=%p, cpu=%p", host, cpu);

158
    if ((driver = cpuGetSubDriver(host->arch)) == NULL)
J
Jiri Denemark 已提交
159 160 161
        return VIR_CPU_COMPARE_ERROR;

    if (driver->compare == NULL) {
162 163
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("cannot compare CPUs of %s architecture"),
164
                       virArchToString(host->arch));
J
Jiri Denemark 已提交
165 166 167
        return VIR_CPU_COMPARE_ERROR;
    }

168
    return driver->compare(host, cpu, failIncompatible);
J
Jiri Denemark 已提交
169 170 171
}


172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
/**
 * cpuDecode:
 *
 * @cpu: CPU definition stub to be filled in
 * @data: internal CPU data to be decoded into @cpu definition
 * @models: list of CPU models that can be considered when decoding @data
 * @nmodels: number of CPU models in @models
 * @preferred: CPU models that should be used if possible
 *
 * Decodes internal CPU data into a CPU definition consisting of a CPU model
 * and a list of CPU features. The @cpu model stub is supposed to have arch,
 * type, match and fallback members set, this function will add the rest. If
 * @models list is NULL, all models supported by libvirt will be considered
 * when decoding the data. In general, this function will select the model
 * closest to the CPU specified by @data unless @preferred is non-NULL, in
 * which case the @preferred model will be used as long as it is compatible
 * with @data.
 *
 * For VIR_ARCH_I686 and VIR_ARCH_X86_64 architectures this means the computed
 * CPU definition will have the shortest possible list of additional features.
 * When @preferred is non-NULL, the @preferred model will be used even if
 * other models would result in a shorter list of additional features.
 *
 * Returns 0 on success, -1 on error.
 */
J
Jiri Denemark 已提交
197
int
198
cpuDecode(virCPUDefPtr cpu,
199
          const virCPUData *data,
200
          const char **models,
201 202
          unsigned int nmodels,
          const char *preferred)
J
Jiri Denemark 已提交
203 204 205
{
    struct cpuArchDriver *driver;

206 207
    VIR_DEBUG("cpu=%p, data=%p, nmodels=%u, preferred=%s",
              cpu, data, nmodels, NULLSTR(preferred));
208
    if (models) {
209
        size_t i;
210
        for (i = 0; i < nmodels; i++)
211
            VIR_DEBUG("models[%zu]=%s", i, NULLSTR(models[i]));
212 213
    }

214
    if (models == NULL && nmodels != 0) {
215 216
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("nonzero nmodels doesn't match with NULL models"));
217 218 219
        return -1;
    }

220 221 222 223
    if (cpu->type > VIR_CPU_TYPE_GUEST ||
        cpu->mode != VIR_CPU_MODE_CUSTOM) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("invalid CPU definition stub"));
J
Jiri Denemark 已提交
224 225 226
        return -1;
    }

227
    if ((driver = cpuGetSubDriver(cpu->arch)) == NULL)
J
Jiri Denemark 已提交
228 229 230
        return -1;

    if (driver->decode == NULL) {
231 232
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("cannot decode CPU data for %s architecture"),
233
                       virArchToString(cpu->arch));
J
Jiri Denemark 已提交
234 235 236
        return -1;
    }

237
    return driver->decode(cpu, data, models, nmodels, preferred, 0);
J
Jiri Denemark 已提交
238 239 240
}


241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
/**
 * cpuEncode:
 *
 * @arch: CPU architecture
 * @cpu: CPU definition to be encoded into internal CPU driver representation
 * @forced: where to store CPU data corresponding to forced features
 * @required: where to store CPU data corresponding to required features
 * @optional: where to store CPU data corresponding to optional features
 * @disabled: where to store CPU data corresponding to disabled features
 * @forbidden: where to store CPU data corresponding to forbidden features
 * @vendor: where to store CPU data corresponding to CPU vendor
 *
 * Encode CPU definition from @cpu into internal CPU driver representation.
 * Any of @forced, @required, @optional, @disabled, @forbidden and @vendor
 * arguments can be NULL in case the caller is not interested in the
 * corresponding data.
 *
 * Returns 0 on success, -1 on error.
 */
J
Jiri Denemark 已提交
260
int
261
cpuEncode(virArch arch,
262
          const virCPUDef *cpu,
263 264 265 266 267 268
          virCPUDataPtr *forced,
          virCPUDataPtr *required,
          virCPUDataPtr *optional,
          virCPUDataPtr *disabled,
          virCPUDataPtr *forbidden,
          virCPUDataPtr *vendor)
J
Jiri Denemark 已提交
269 270 271
{
    struct cpuArchDriver *driver;

272
    VIR_DEBUG("arch=%s, cpu=%p, forced=%p, required=%p, "
J
Jiri Denemark 已提交
273
              "optional=%p, disabled=%p, forbidden=%p, vendor=%p",
274
              virArchToString(arch), cpu, forced, required,
J
Jiri Denemark 已提交
275
              optional, disabled, forbidden, vendor);
276

277 278 279 280 281 282
    if (!cpu->model) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("no guest CPU model specified"));
        return -1;
    }

283
    if ((driver = cpuGetSubDriver(arch)) == NULL)
J
Jiri Denemark 已提交
284 285 286
        return -1;

    if (driver->encode == NULL) {
287 288
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("cannot encode CPU data for %s architecture"),
289
                       virArchToString(arch));
J
Jiri Denemark 已提交
290 291 292
        return -1;
    }

J
Jiri Denemark 已提交
293
    return driver->encode(arch, cpu, forced, required,
J
Jiri Denemark 已提交
294
                          optional, disabled, forbidden, vendor);
J
Jiri Denemark 已提交
295 296 297
}


298 299 300 301 302 303 304 305 306
/**
 * cpuDataFree:
 *
 * @data: CPU data structure to be freed
 *
 * Free internal CPU data.
 *
 * Returns nothing.
 */
J
Jiri Denemark 已提交
307
void
J
Jiri Denemark 已提交
308
cpuDataFree(virCPUDataPtr data)
J
Jiri Denemark 已提交
309 310 311
{
    struct cpuArchDriver *driver;

J
Jiri Denemark 已提交
312
    VIR_DEBUG("data=%p", data);
313

J
Jiri Denemark 已提交
314 315 316
    if (data == NULL)
        return;

J
Jiri Denemark 已提交
317
    if ((driver = cpuGetSubDriver(data->arch)) == NULL)
J
Jiri Denemark 已提交
318 319 320
        return;

    if (driver->free == NULL) {
321 322
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("cannot free CPU data for %s architecture"),
J
Jiri Denemark 已提交
323
                       virArchToString(data->arch));
J
Jiri Denemark 已提交
324 325 326
        return;
    }

E
Eric Blake 已提交
327
    (driver->free)(data);
J
Jiri Denemark 已提交
328 329 330
}


331 332 333 334 335 336 337
/**
 * cpuNodeData:
 *
 * @arch: CPU architecture
 *
 * Returns CPU data for host CPU or NULL on error.
 */
338
virCPUDataPtr
339
cpuNodeData(virArch arch)
J
Jiri Denemark 已提交
340 341 342
{
    struct cpuArchDriver *driver;

343
    VIR_DEBUG("arch=%s", virArchToString(arch));
344

345
    if ((driver = cpuGetSubDriver(arch)) == NULL)
J
Jiri Denemark 已提交
346 347 348
        return NULL;

    if (driver->nodeData == NULL) {
349 350
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("cannot get node CPU data for %s architecture"),
351
                       virArchToString(arch));
J
Jiri Denemark 已提交
352 353 354
        return NULL;
    }

355
    return driver->nodeData(arch);
J
Jiri Denemark 已提交
356 357 358
}


359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
/**
 * cpuGuestData:
 *
 * @host: host CPU definition
 * @guest: guest CPU definition
 * @data: computed guest CPU data
 * @msg: error message describing why the @guest and @host CPUs are considered
 *       incompatible
 *
 * Computes guest CPU data for the @guest CPU definition when run on the @host
 * CPU.
 *
 * Returns VIR_CPU_COMPARE_ERROR on error, VIR_CPU_COMPARE_INCOMPATIBLE when
 * the two CPUs are incompatible (@msg will describe the incompatibility),
 * VIR_CPU_COMPARE_IDENTICAL when the two CPUs are identical,
 * VIR_CPU_COMPARE_SUPERSET when the @guest CPU is a superset of the @host CPU.
 */
J
Jiri Denemark 已提交
376
virCPUCompareResult
377
cpuGuestData(virCPUDefPtr host,
J
Jiri Denemark 已提交
378
             virCPUDefPtr guest,
379
             virCPUDataPtr *data,
380
             char **msg)
J
Jiri Denemark 已提交
381 382 383
{
    struct cpuArchDriver *driver;

384
    VIR_DEBUG("host=%p, guest=%p, data=%p, msg=%p", host, guest, data, msg);
385

386
    if ((driver = cpuGetSubDriver(host->arch)) == NULL)
J
Jiri Denemark 已提交
387 388 389
        return VIR_CPU_COMPARE_ERROR;

    if (driver->guestData == NULL) {
390 391
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("cannot compute guest CPU data for %s architecture"),
392
                       virArchToString(host->arch));
J
Jiri Denemark 已提交
393 394 395
        return VIR_CPU_COMPARE_ERROR;
    }

396
    return driver->guestData(host, guest, data, msg);
J
Jiri Denemark 已提交
397
}
398 399


400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
/**
 * cpuBaselineXML:
 *
 * @xmlCPUs: list of host CPU XML descriptions
 * @ncpus: number of CPUs in @xmlCPUs
 * @models: list of CPU models that can be considered for the baseline CPU
 * @nmodels: number of CPU models in @models
 * @flags: bitwise-OR of virConnectBaselineCPUFlags
 *
 * Computes the most feature-rich CPU which is compatible with all given
 * host CPUs. If @models array is NULL, all models supported by libvirt will
 * be considered when computing the baseline CPU model, otherwise the baseline
 * CPU model will be one of the provided CPU @models.
 *
 * If @flags includes VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES then libvirt
 * will explicitly list all CPU features that are part of the host CPU,
 * without this flag features that are part of the CPU model will not be
 * listed.
 *
 * Returns XML description of the baseline CPU or NULL on error.
 */
421 422 423 424
char *
cpuBaselineXML(const char **xmlCPUs,
               unsigned int ncpus,
               const char **models,
425 426
               unsigned int nmodels,
               unsigned int flags)
427 428 429 430 431 432
{
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
    virCPUDefPtr *cpus = NULL;
    virCPUDefPtr cpu = NULL;
    char *cpustr;
433
    size_t i;
434

435 436 437
    VIR_DEBUG("ncpus=%u, nmodels=%u", ncpus, nmodels);
    if (xmlCPUs) {
        for (i = 0; i < ncpus; i++)
438
            VIR_DEBUG("xmlCPUs[%zu]=%s", i, NULLSTR(xmlCPUs[i]));
439 440 441
    }
    if (models) {
        for (i = 0; i < nmodels; i++)
442
            VIR_DEBUG("models[%zu]=%s", i, NULLSTR(models[i]));
443 444
    }

445
    if (xmlCPUs == NULL && ncpus != 0) {
446 447
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("nonzero ncpus doesn't match with NULL xmlCPUs"));
448 449 450 451
        return NULL;
    }

    if (ncpus < 1) {
452
        virReportError(VIR_ERR_INVALID_ARG, "%s", _("No CPUs given"));
453 454 455 456
        return NULL;
    }

    if (VIR_ALLOC_N(cpus, ncpus))
457
        goto error;
458 459

    for (i = 0; i < ncpus; i++) {
460
        if (!(doc = virXMLParseStringCtxt(xmlCPUs[i], _("(CPU_definition)"), &ctxt)))
461 462
            goto error;

463 464 465 466 467 468 469 470 471 472
        cpus[i] = virCPUDefParseXML(ctxt->node, ctxt, VIR_CPU_TYPE_HOST);
        if (cpus[i] == NULL)
            goto error;

        xmlXPathFreeContext(ctxt);
        xmlFreeDoc(doc);
        ctxt = NULL;
        doc = NULL;
    }

473
    if (!(cpu = cpuBaseline(cpus, ncpus, models, nmodels, flags)))
474 475
        goto error;

476
    cpustr = virCPUDefFormat(cpu, NULL, false);
477

478
 cleanup:
479 480 481 482 483 484 485 486 487 488 489
    if (cpus) {
        for (i = 0; i < ncpus; i++)
            virCPUDefFree(cpus[i]);
        VIR_FREE(cpus);
    }
    virCPUDefFree(cpu);
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);

    return cpustr;

490
 error:
491 492 493 494 495
    cpustr = NULL;
    goto cleanup;
}


496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
/**
 * cpuBaseline:
 *
 * @cpus: list of host CPU definitions
 * @ncpus: number of CPUs in @cpus
 * @models: list of CPU models that can be considered for the baseline CPU
 * @nmodels: number of CPU models in @models
 * @flags: bitwise-OR of virConnectBaselineCPUFlags
 *
 * Computes the most feature-rich CPU which is compatible with all given
 * host CPUs. If @models array is NULL, all models supported by libvirt will
 * be considered when computing the baseline CPU model, otherwise the baseline
 * CPU model will be one of the provided CPU @models.
 *
 * If @flags includes VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES then libvirt
 * will explicitly list all CPU features that are part of the host CPU,
 * without this flag features that are part of the CPU model will not be
 * listed.
 *
 * Returns baseline CPU definition or NULL on error.
 */
517 518 519 520
virCPUDefPtr
cpuBaseline(virCPUDefPtr *cpus,
            unsigned int ncpus,
            const char **models,
521 522
            unsigned int nmodels,
            unsigned int flags)
523 524
{
    struct cpuArchDriver *driver;
525
    size_t i;
526 527 528 529

    VIR_DEBUG("ncpus=%u, nmodels=%u", ncpus, nmodels);
    if (cpus) {
        for (i = 0; i < ncpus; i++)
530
            VIR_DEBUG("cpus[%zu]=%p", i, cpus[i]);
531 532 533
    }
    if (models) {
        for (i = 0; i < nmodels; i++)
534
            VIR_DEBUG("models[%zu]=%s", i, NULLSTR(models[i]));
535
    }
536 537

    if (cpus == NULL && ncpus != 0) {
538 539
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("nonzero ncpus doesn't match with NULL cpus"));
540 541 542 543
        return NULL;
    }

    if (ncpus < 1) {
544
        virReportError(VIR_ERR_INVALID_ARG, "%s", _("No CPUs given"));
545 546 547
        return NULL;
    }

548 549 550 551 552 553 554 555 556 557 558 559 560
    for (i = 0; i < ncpus; i++) {
        if (!cpus[i]) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("invalid CPU definition at index %zu"), i);
            return NULL;
        }
        if (!cpus[i]->model) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("no CPU model specified at index %zu"), i);
            return NULL;
        }
    }

561
    if (models == NULL && nmodels != 0) {
562 563
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("nonzero nmodels doesn't match with NULL models"));
564 565 566 567 568 569 570
        return NULL;
    }

    if ((driver = cpuGetSubDriver(cpus[0]->arch)) == NULL)
        return NULL;

    if (driver->baseline == NULL) {
571 572
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("cannot compute baseline CPU of %s architecture"),
573
                       virArchToString(cpus[0]->arch));
574 575 576
        return NULL;
    }

577
    return driver->baseline(cpus, ncpus, models, nmodels, flags);
578
}
579 580


581
/**
J
Jiri Denemark 已提交
582
 * virCPUUpdate:
583
 *
J
Jiri Denemark 已提交
584 585
 * @arch: CPU architecture
 * @guest: guest CPU definition to be updated
586 587 588
 * @host: host CPU definition
 *
 * Updates @guest CPU definition according to @host CPU. This is required to
J
Jiri Denemark 已提交
589 590 591 592 593
 * support guest CPU definitions specified relatively to host CPU, such as
 * CPUs with VIR_CPU_MODE_CUSTOM and optional features or
 * VIR_CPU_MATCH_MINIMUM, or CPUs with VIR_CPU_MODE_HOST_MODEL.
 * When the guest CPU was not specified relatively, the function does nothing
 * and returns success.
594 595 596
 *
 * Returns 0 on success, -1 on error.
 */
597
int
J
Jiri Denemark 已提交
598 599 600
virCPUUpdate(virArch arch,
             virCPUDefPtr guest,
             const virCPUDef *host)
601 602 603
{
    struct cpuArchDriver *driver;

J
Jiri Denemark 已提交
604 605 606
    VIR_DEBUG("arch=%s, guest=%p mode=%s model=%s, host=%p model=%s",
              virArchToString(arch), guest, virCPUModeTypeToString(guest->mode),
              NULLSTR(guest->model), host, NULLSTR(host ? host->model : NULL));
607

J
Jiri Denemark 已提交
608
    if (!(driver = cpuGetSubDriver(arch)))
609 610
        return -1;

J
Jiri Denemark 已提交
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
    if (guest->mode == VIR_CPU_MODE_HOST_PASSTHROUGH)
        return 0;

    if (guest->mode == VIR_CPU_MODE_CUSTOM &&
        guest->match != VIR_CPU_MATCH_MINIMUM) {
        size_t i;
        bool optional = false;

        for (i = 0; i < guest->nfeatures; i++) {
            if (guest->features[i].policy == VIR_CPU_FEATURE_OPTIONAL) {
                optional = true;
                break;
            }
        }

        if (!optional)
            return 0;
    }

    /* We get here if guest CPU is either
     *  - host-model
     *  - custom with minimum match
     *  - custom with optional features
     */
    if (!driver->update) {
636
        virReportError(VIR_ERR_NO_SUPPORT,
J
Jiri Denemark 已提交
637 638
                       _("cannot update guest CPU for %s architecture"),
                       virArchToString(arch));
639 640 641
        return -1;
    }

J
Jiri Denemark 已提交
642 643 644 645 646
    if (driver->update(guest, host) < 0)
        return -1;

    VIR_DEBUG("model=%s", NULLSTR(guest->model));
    return 0;
647
}
D
Daniel P. Berrange 已提交
648

649 650 651 652 653 654 655 656 657 658 659 660

/**
 * cpuHasFeature:
 *
 * @data: internal CPU representation
 * @feature: feature to be checked for
 *
 * Checks whether @feature is supported by the CPU described by @data.
 *
 * Returns 1 if the feature is supported, 0 if it's not supported, or
 * -1 on error.
 */
D
Daniel P. Berrange 已提交
661
int
662
cpuHasFeature(const virCPUData *data,
D
Daniel P. Berrange 已提交
663 664 665 666
              const char *feature)
{
    struct cpuArchDriver *driver;

J
Jiri Denemark 已提交
667
    VIR_DEBUG("data=%p, feature=%s", data, feature);
D
Daniel P. Berrange 已提交
668

J
Jiri Denemark 已提交
669
    if ((driver = cpuGetSubDriver(data->arch)) == NULL)
D
Daniel P. Berrange 已提交
670 671 672
        return -1;

    if (driver->hasFeature == NULL) {
673 674
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("cannot check guest CPU data for %s architecture"),
J
Jiri Denemark 已提交
675
                       virArchToString(data->arch));
D
Daniel P. Berrange 已提交
676 677 678 679 680
        return -1;
    }

    return driver->hasFeature(data, feature);
}
681

682 683 684 685 686 687 688 689 690 691

/**
 * cpuDataFormat:
 *
 * @data: internal CPU representation
 *
 * Formats @data into XML for test purposes.
 *
 * Returns string representation of the XML describing @data or NULL on error.
 */
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
char *
cpuDataFormat(const virCPUData *data)
{
    struct cpuArchDriver *driver;

    VIR_DEBUG("data=%p", data);

    if (!(driver = cpuGetSubDriver(data->arch)))
        return NULL;

    if (!driver->dataFormat) {
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("cannot format %s CPU data"),
                       virArchToString(data->arch));
        return NULL;
    }

    return driver->dataFormat(data);
}

712 713 714 715 716 717 718 719 720 721

/**
 * cpuDataParse:
 *
 * @xmlStr: XML string produced by cpuDataFormat
 *
 * Parses XML representation of virCPUData structure for test purposes.
 *
 * Returns internal CPU data structure parsed from the XML or NULL on error.
 */
722
virCPUDataPtr
723
cpuDataParse(const char *xmlStr)
724 725
{
    struct cpuArchDriver *driver;
726 727 728 729
    xmlDocPtr xml = NULL;
    xmlXPathContextPtr ctxt = NULL;
    virCPUDataPtr data = NULL;
    char *arch = NULL;
730

731
    VIR_DEBUG("xmlStr=%s", xmlStr);
732

733 734 735 736 737 738 739 740 741 742 743 744 745 746
    if (!(xml = virXMLParseStringCtxt(xmlStr, _("CPU data"), &ctxt))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("cannot parse CPU data"));
        goto cleanup;
    }

    if (!(arch = virXPathString("string(/cpudata/@arch)", ctxt))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("missing CPU data architecture"));
        goto cleanup;
    }

    if (!(driver = cpuGetSubDriverByName(arch)))
        goto cleanup;
747 748 749

    if (!driver->dataParse) {
        virReportError(VIR_ERR_NO_SUPPORT,
750 751
                       _("cannot parse %s CPU data"), arch);
        goto cleanup;
752 753
    }

754 755 756 757 758 759 760
    data = driver->dataParse(ctxt);

 cleanup:
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(xml);
    VIR_FREE(arch);
    return data;
761 762
}

763 764 765 766 767
bool
cpuModelIsAllowed(const char *model,
                  const char **models,
                  unsigned int nmodels)
{
768
    size_t i;
769 770 771 772 773 774 775 776 777 778

    if (!models || !nmodels)
        return true;

    for (i = 0; i < nmodels; i++) {
        if (models[i] && STREQ(models[i], model))
            return true;
    }
    return false;
}
779

780 781 782
/**
 * cpuGetModels:
 *
J
Jiri Denemark 已提交
783
 * @arch: CPU architecture
784
 * @models: where to store the NULL-terminated list of supported models
785
 *
786 787 788 789
 * Fetches all CPU models supported by libvirt on @archName. If there are
 * no restrictions on CPU models on @archName (i.e., the CPU model is just
 * passed directly to a hypervisor), this function returns 0 and sets
 * @models to NULL.
790
 *
791 792
 * Returns number of supported CPU models, 0 if any CPU model is supported,
 * or -1 on error.
793
 */
794
int
J
Jiri Denemark 已提交
795
cpuGetModels(virArch arch, char ***models)
796 797 798
{
    struct cpuArchDriver *driver;

J
Jiri Denemark 已提交
799
    VIR_DEBUG("arch=%s", virArchToString(arch));
800

801
    if (!(driver = cpuGetSubDriver(arch)))
802
        return -1;
803

804
    if (!driver->getModels) {
805 806 807
        if (models)
            *models = NULL;
        return 0;
808
    }
809

810
    return driver->getModels(models);
811
}
J
Jiri Denemark 已提交
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870


/**
 * virCPUTranslate:
 *
 * @arch: CPU architecture
 * @cpu: CPU definition to be translated
 * @models: NULL-terminated list of allowed CPU models (NULL if all are allowed)
 * @nmodels: number of CPU models in @models
 *
 * Translates @cpu model (if allowed by @cpu->fallback) to a closest CPU model
 * from @models list.
 *
 * The function does nothing (and returns 0) if @cpu does not have to be
 * translated.
 *
 * Returns -1 on error, 0 on success.
 */
int
virCPUTranslate(virArch arch,
                virCPUDefPtr cpu,
                char **models,
                unsigned int nmodels)
{
    struct cpuArchDriver *driver;

    VIR_DEBUG("arch=%s, cpu=%p, model=%s, models=%p, nmodels=%u",
              virArchToString(arch), cpu, NULLSTR(cpu->model), models, nmodels);

    if (!(driver = cpuGetSubDriver(arch)))
        return -1;

    if (cpu->mode == VIR_CPU_MODE_HOST_MODEL ||
        cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH)
        return 0;

    if (cpuModelIsAllowed(cpu->model, (const char **) models, nmodels))
        return 0;

    if (cpu->fallback != VIR_CPU_FALLBACK_ALLOW) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("CPU model %s is not supported by hypervisor"),
                       cpu->model);
        return -1;
    }

    if (!driver->translate) {
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("cannot translate CPU model %s to a supported model"),
                       cpu->model);
        return -1;
    }

    if (driver->translate(cpu, (const char **) models, nmodels) < 0)
        return -1;

    VIR_DEBUG("model=%s", NULLSTR(cpu->model));
    return 0;
}