cpu_ppc64.c 18.6 KB
Newer Older
P
Prerna Saxena 已提交
1
/*
2
 * cpu_ppc64.c: CPU driver for 64-bit PowerPC CPUs
P
Prerna Saxena 已提交
3
 *
4
 * Copyright (C) 2013 Red Hat, Inc.
L
Li Zhang 已提交
5
 * Copyright (C) IBM Corporation, 2010
P
Prerna Saxena 已提交
6 7 8 9 10 11 12 13 14 15 16 17
 *
 * 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
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
P
Prerna Saxena 已提交
20 21 22 23
 *
 * Authors:
 *      Anton Blanchard <anton@au.ibm.com>
 *      Prerna Saxena <prerna@linux.vnet.ibm.com>
L
Li Zhang 已提交
24
 *      Li Zhang <zhlcindy@linux.vnet.ibm.com>
P
Prerna Saxena 已提交
25 26 27
 */

#include <config.h>
L
Li Zhang 已提交
28
#include <stdint.h>
P
Prerna Saxena 已提交
29

30
#include "virlog.h"
31
#include "viralloc.h"
P
Prerna Saxena 已提交
32
#include "cpu.h"
33
#include "virstring.h"
L
Li Zhang 已提交
34
#include "cpu_map.h"
35
#include "virbuffer.h"
P
Prerna Saxena 已提交
36 37 38

#define VIR_FROM_THIS VIR_FROM_CPU

39
VIR_LOG_INIT("cpu.cpu_ppc64");
40

41
static const virArch archs[] = { VIR_ARCH_PPC64, VIR_ARCH_PPC64LE };
P
Prerna Saxena 已提交
42

43
struct ppc64_vendor {
L
Li Zhang 已提交
44
    char *name;
45
    struct ppc64_vendor *next;
L
Li Zhang 已提交
46 47
};

48
struct ppc64_model {
L
Li Zhang 已提交
49
    char *name;
50
    const struct ppc64_vendor *vendor;
51
    virCPUppc64Data *data;
52
    struct ppc64_model *next;
L
Li Zhang 已提交
53 54
};

55 56 57
struct ppc64_map {
    struct ppc64_vendor *vendors;
    struct ppc64_model *models;
L
Li Zhang 已提交
58 59
};

60 61 62
static void
ppc64DataFree(virCPUppc64Data *data)
{
63 64 65 66
    if (!data)
        return;

    VIR_FREE(data->pvr);
67 68 69 70 71 72 73
    VIR_FREE(data);
}

static virCPUppc64Data *
ppc64DataCopy(const virCPUppc64Data *data)
{
    virCPUppc64Data *copy;
74
    size_t i;
75 76

    if (VIR_ALLOC(copy) < 0)
77 78 79 80
        goto error;

    if (VIR_ALLOC_N(copy->pvr, data->len) < 0)
        goto error;
81

82 83 84 85
    copy->len = data->len;

    for (i = 0; i < data->len; i++)
        copy->pvr[i].value = data->pvr[i].value;
86 87

    return copy;
88 89 90 91

 error:
    ppc64DataFree(copy);
    return NULL;
92 93
}

94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
static void
ppc64VendorFree(struct ppc64_vendor *vendor)
{
    if (!vendor)
        return;

    VIR_FREE(vendor->name);
    VIR_FREE(vendor);
}

static struct ppc64_vendor *
ppc64VendorFind(const struct ppc64_map *map,
                const char *name)
{
    struct ppc64_vendor *vendor;

    vendor = map->vendors;
    while (vendor) {
        if (STREQ(vendor->name, name))
            return vendor;

        vendor = vendor->next;
    }

    return NULL;
}
L
Li Zhang 已提交
120 121

static void
122
ppc64ModelFree(struct ppc64_model *model)
L
Li Zhang 已提交
123
{
124
    if (!model)
L
Li Zhang 已提交
125 126
        return;

127
    ppc64DataFree(model->data);
L
Li Zhang 已提交
128 129 130 131
    VIR_FREE(model->name);
    VIR_FREE(model);
}

132 133 134 135 136
static struct ppc64_model *
ppc64ModelCopy(const struct ppc64_model *model)
{
    struct ppc64_model *copy;

137 138 139 140 141 142 143 144
    if (VIR_ALLOC(copy) < 0)
        goto error;

    if (VIR_STRDUP(copy->name, model->name) < 0)
        goto error;

    if (!(copy->data = ppc64DataCopy(model->data)))
        goto error;
145 146 147 148

    copy->vendor = model->vendor;

    return copy;
149 150 151 152

 error:
    ppc64ModelFree(copy);
    return NULL;
153 154
}

155 156 157
static struct ppc64_model *
ppc64ModelFind(const struct ppc64_map *map,
               const char *name)
L
Li Zhang 已提交
158
{
159
    struct ppc64_model *model;
L
Li Zhang 已提交
160 161

    model = map->models;
162
    while (model) {
L
Li Zhang 已提交
163 164 165 166 167 168 169 170 171
        if (STREQ(model->name, name))
            return model;

        model = model->next;
    }

    return NULL;
}

172 173 174
static struct ppc64_model *
ppc64ModelFindPVR(const struct ppc64_map *map,
                  uint32_t pvr)
175
{
176
    struct ppc64_model *model;
177
    size_t i;
178 179

    model = map->models;
180
    while (model) {
181 182 183 184
        for (i = 0; i < model->data->len; i++) {
            if (model->data->pvr[i].value == pvr)
                return model;
        }
185 186 187
        model = model->next;
    }

188 189 190
    /* PowerPC Processor Version Register is interpreted as follows :
     * Higher order 16 bits : Power ISA generation.
     * Lower order 16 bits : CPU chip version number.
M
Martin Kletzander 已提交
191
     * If the exact CPU isn't found, return the nearest matching CPU generation
192 193
     */
    if (pvr & 0x0000FFFFul)
194
        return ppc64ModelFindPVR(map, (pvr & 0xFFFF0000ul));
195

196 197 198
    return NULL;
}

199
static struct ppc64_model *
200 201
ppc64ModelFromCPU(const virCPUDef *cpu,
                  const struct ppc64_map *map)
202
{
203
    struct ppc64_model *model;
204

205 206 207
    if (!(model = ppc64ModelFind(map, cpu->model))) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unknown CPU model %s"), cpu->model);
208 209 210
        return NULL;
    }

211
    return ppc64ModelCopy(model);
L
Li Zhang 已提交
212 213 214
}

static void
215
ppc64MapFree(struct ppc64_map *map)
L
Li Zhang 已提交
216
{
217
    if (!map)
L
Li Zhang 已提交
218 219
        return;

220 221 222 223 224
    while (map->models) {
        struct ppc64_model *model = map->models;
        map->models = model->next;
        ppc64ModelFree(model);
    }
225

226 227 228 229
    while (map->vendors) {
        struct ppc64_vendor *vendor = map->vendors;
        map->vendors = vendor->next;
        ppc64VendorFree(vendor);
230 231
    }

232
    VIR_FREE(map);
233 234
}

L
Li Zhang 已提交
235
static int
236 237
ppc64VendorLoad(xmlXPathContextPtr ctxt,
                struct ppc64_map *map)
L
Li Zhang 已提交
238
{
239
    struct ppc64_vendor *vendor;
L
Li Zhang 已提交
240

241
    if (VIR_ALLOC(vendor) < 0)
242
        return -1;
L
Li Zhang 已提交
243 244 245 246 247 248 249 250

    vendor->name = virXPathString("string(@name)", ctxt);
    if (!vendor->name) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Missing CPU vendor name"));
        goto ignore;
    }

251
    if (ppc64VendorFind(map, vendor->name)) {
L
Li Zhang 已提交
252 253 254 255 256
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("CPU vendor %s already defined"), vendor->name);
        goto ignore;
    }

257
    if (!map->vendors) {
L
Li Zhang 已提交
258
        map->vendors = vendor;
259
    } else {
L
Li Zhang 已提交
260 261 262 263
        vendor->next = map->vendors;
        map->vendors = vendor;
    }

264
 cleanup:
265
    return 0;
L
Li Zhang 已提交
266

267
 ignore:
268
    ppc64VendorFree(vendor);
269
    goto cleanup;
L
Li Zhang 已提交
270 271 272
}

static int
273 274
ppc64ModelLoad(xmlXPathContextPtr ctxt,
               struct ppc64_map *map)
L
Li Zhang 已提交
275
{
276
    struct ppc64_model *model;
277 278
    xmlNodePtr *nodes = NULL;
    xmlNodePtr bookmark;
L
Li Zhang 已提交
279
    char *vendor = NULL;
280
    unsigned long pvr;
281 282 283 284 285 286
    size_t i;
    int n;

    /* Save the node the context was pointing to, as we're going
     * to change it later. It's going to be restored on exit */
    bookmark = ctxt->node;
L
Li Zhang 已提交
287

288
    if (VIR_ALLOC(model) < 0)
289
        return -1;
L
Li Zhang 已提交
290

291 292 293 294 295
    if (VIR_ALLOC(model->data) < 0) {
        ppc64ModelFree(model);
        return -1;
    }

L
Li Zhang 已提交
296
    model->name = virXPathString("string(@name)", ctxt);
297
    if (!model->name) {
L
Li Zhang 已提交
298 299 300 301 302
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Missing CPU model name"));
        goto ignore;
    }

303
    if (ppc64ModelFind(map, model->name)) {
304 305 306 307
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("CPU model %s already defined"), model->name);
        goto ignore;
    }
L
Li Zhang 已提交
308 309 310 311 312 313 314 315 316 317

    if (virXPathBoolean("boolean(./vendor)", ctxt)) {
        vendor = virXPathString("string(./vendor/@name)", ctxt);
        if (!vendor) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Invalid vendor element in CPU model %s"),
                           model->name);
            goto ignore;
        }

318
        if (!(model->vendor = ppc64VendorFind(map, vendor))) {
L
Li Zhang 已提交
319 320 321 322 323 324 325
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unknown vendor %s referenced by CPU model %s"),
                           vendor, model->name);
            goto ignore;
        }
    }

326
    if ((n = virXPathNodeSet("./pvr", ctxt, &nodes)) <= 0) {
327
        virReportError(VIR_ERR_INTERNAL_ERROR,
328
                       _("Missing PVR information for CPU model %s"),
329 330 331
                       model->name);
        goto ignore;
    }
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348

    if (VIR_ALLOC_N(model->data->pvr, n) < 0)
        goto ignore;

    model->data->len = n;

    for (i = 0; i < n; i++) {
        ctxt->node = nodes[i];

        if (virXPathULongHex("string(./@value)", ctxt, &pvr) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Missing or invalid PVR value in CPU model %s"),
                           model->name);
            goto ignore;
        }
        model->data->pvr[i].value = pvr;
    }
349

350
    if (!map->models) {
L
Li Zhang 已提交
351
        map->models = model;
352
    } else {
L
Li Zhang 已提交
353 354 355 356
        model->next = map->models;
        map->models = model;
    }

357
 cleanup:
358
    ctxt->node = bookmark;
L
Li Zhang 已提交
359
    VIR_FREE(vendor);
360
    VIR_FREE(nodes);
361
    return 0;
L
Li Zhang 已提交
362

363
 ignore:
364
    ppc64ModelFree(model);
365
    goto cleanup;
L
Li Zhang 已提交
366 367 368
}

static int
369 370 371
ppc64MapLoadCallback(cpuMapElement element,
                     xmlXPathContextPtr ctxt,
                     void *data)
L
Li Zhang 已提交
372
{
373
    struct ppc64_map *map = data;
L
Li Zhang 已提交
374 375 376

    switch (element) {
    case CPU_MAP_ELEMENT_VENDOR:
377
        return ppc64VendorLoad(ctxt, map);
L
Li Zhang 已提交
378
    case CPU_MAP_ELEMENT_MODEL:
379
        return ppc64ModelLoad(ctxt, map);
380 381
    case CPU_MAP_ELEMENT_FEATURE:
    case CPU_MAP_ELEMENT_LAST:
L
Li Zhang 已提交
382 383 384 385 386 387
        break;
    }

    return 0;
}

388 389
static struct ppc64_map *
ppc64LoadMap(void)
L
Li Zhang 已提交
390
{
391
    struct ppc64_map *map;
L
Li Zhang 已提交
392

393
    if (VIR_ALLOC(map) < 0)
394
        goto error;
L
Li Zhang 已提交
395

396
    if (cpuMapLoad("ppc64", ppc64MapLoadCallback, map) < 0)
L
Li Zhang 已提交
397 398 399 400
        goto error;

    return map;

401
 error:
402
    ppc64MapFree(map);
L
Li Zhang 已提交
403 404 405
    return NULL;
}

406
static virCPUDataPtr
407
ppc64MakeCPUData(virArch arch,
408
                 virCPUppc64Data *data)
409 410 411 412 413 414 415
{
    virCPUDataPtr cpuData;

    if (VIR_ALLOC(cpuData) < 0)
        return NULL;

    cpuData->arch = arch;
416 417 418

    if (!(cpuData->data.ppc64 = ppc64DataCopy(data)))
        VIR_FREE(cpuData);
419 420 421 422 423

    return cpuData;
}

static virCPUCompareResult
424 425 426 427
ppc64Compute(virCPUDefPtr host,
             const virCPUDef *cpu,
             virCPUDataPtr *guestData,
             char **message)
428
{
429 430 431
    struct ppc64_map *map = NULL;
    struct ppc64_model *host_model = NULL;
    struct ppc64_model *guest_model = NULL;
432

433
    virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR;
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
    virArch arch;
    size_t i;

    if (cpu->arch != VIR_ARCH_NONE) {
        bool found = false;

        for (i = 0; i < ARRAY_CARDINALITY(archs); i++) {
            if (archs[i] == cpu->arch) {
                found = true;
                break;
            }
        }

        if (!found) {
            VIR_DEBUG("CPU arch %s does not match host arch",
                      virArchToString(cpu->arch));
            if (message &&
                virAsprintf(message,
                            _("CPU arch %s does not match host arch"),
                            virArchToString(cpu->arch)) < 0)
454 455 456 457
                goto cleanup;

            ret = VIR_CPU_COMPARE_INCOMPATIBLE;
            goto cleanup;
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
        }
        arch = cpu->arch;
    } else {
        arch = host->arch;
    }

    if (cpu->vendor &&
        (!host->vendor || STRNEQ(cpu->vendor, host->vendor))) {
        VIR_DEBUG("host CPU vendor does not match required CPU vendor %s",
                  cpu->vendor);
        if (message &&
            virAsprintf(message,
                        _("host CPU vendor does not match required "
                        "CPU vendor %s"),
                        cpu->vendor) < 0)
473 474 475 476
            goto cleanup;

        ret = VIR_CPU_COMPARE_INCOMPATIBLE;
        goto cleanup;
477 478
    }

479 480 481
    if (!(map = ppc64LoadMap()) ||
        !(host_model = ppc64ModelFromCPU(host, map)) ||
        !(guest_model = ppc64ModelFromCPU(cpu, map)))
482
        goto cleanup;
483

484
    if (STRNEQ(guest_model->name, host_model->name)) {
485 486 487 488 489 490 491
        VIR_DEBUG("host CPU model does not match required CPU model %s",
                  guest_model->name);
        if (message &&
            virAsprintf(message,
                        _("host CPU model does not match required "
                        "CPU model %s"),
                        guest_model->name) < 0)
492
            goto cleanup;
493

494 495 496 497 498
        ret = VIR_CPU_COMPARE_INCOMPATIBLE;
        goto cleanup;
    }

    if (guestData)
499
        if (!(*guestData = ppc64MakeCPUData(arch, guest_model->data)))
500
            goto cleanup;
501 502 503

    ret = VIR_CPU_COMPARE_IDENTICAL;

504
 cleanup:
505 506 507
    ppc64MapFree(map);
    ppc64ModelFree(host_model);
    ppc64ModelFree(guest_model);
508 509 510
    return ret;
}

L
Li Zhang 已提交
511
static virCPUCompareResult
512 513 514
ppc64DriverCompare(virCPUDefPtr host,
                   virCPUDefPtr cpu,
                   bool failIncompatible)
L
Li Zhang 已提交
515
{
516 517
    virCPUCompareResult ret;
    char *message = NULL;
L
Li Zhang 已提交
518

519 520 521 522 523 524 525 526 527
    ret = ppc64Compute(host, cpu, NULL, &message);

    if (failIncompatible && ret == VIR_CPU_COMPARE_INCOMPATIBLE) {
        ret = VIR_CPU_COMPARE_ERROR;
        if (message) {
            virReportError(VIR_ERR_CPU_INCOMPATIBLE, "%s", message);
        } else {
            virReportError(VIR_ERR_CPU_INCOMPATIBLE, NULL);
        }
528
    }
529 530 531
    VIR_FREE(message);

    return ret;
L
Li Zhang 已提交
532 533 534
}

static int
535 536 537 538 539 540
ppc64DriverDecode(virCPUDefPtr cpu,
                  const virCPUData *data,
                  const char **models,
                  unsigned int nmodels,
                  const char *preferred ATTRIBUTE_UNUSED,
                  unsigned int flags)
L
Li Zhang 已提交
541 542
{
    int ret = -1;
543 544
    struct ppc64_map *map;
    const struct ppc64_model *model;
L
Li Zhang 已提交
545

546 547
    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, -1);

548
    if (!data || !(map = ppc64LoadMap()))
L
Li Zhang 已提交
549 550
        return -1;

551
    if (!(model = ppc64ModelFindPVR(map, data->data.ppc64->pvr[0].value))) {
552 553
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("Cannot find CPU model with PVR 0x%08x"),
554
                       data->data.ppc64->pvr[0].value);
J
Jiri Denemark 已提交
555
        goto cleanup;
556
    }
L
Li Zhang 已提交
557

558
    if (!cpuModelIsAllowed(model->name, models, nmodels)) {
J
Jiri Denemark 已提交
559 560
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("CPU model %s is not supported by hypervisor"),
561
                       model->name);
J
Jiri Denemark 已提交
562
        goto cleanup;
L
Li Zhang 已提交
563 564
    }

565 566
    if (VIR_STRDUP(cpu->model, model->name) < 0 ||
        (model->vendor && VIR_STRDUP(cpu->vendor, model->vendor->name) < 0)) {
567 568
        goto cleanup;
    }
L
Li Zhang 已提交
569 570 571

    ret = 0;

572
 cleanup:
573
    ppc64MapFree(map);
L
Li Zhang 已提交
574 575 576 577 578

    return ret;
}

static void
579
ppc64DriverFree(virCPUDataPtr data)
L
Li Zhang 已提交
580
{
581
    if (!data)
L
Li Zhang 已提交
582 583
        return;

584
    ppc64DataFree(data->data.ppc64);
L
Li Zhang 已提交
585 586 587
    VIR_FREE(data);
}

588
static virCPUDataPtr
589
ppc64DriverNodeData(virArch arch)
P
Prerna Saxena 已提交
590
{
591 592
    virCPUDataPtr nodeData;
    virCPUppc64Data *data;
P
Prerna Saxena 已提交
593

594 595
    if (VIR_ALLOC(nodeData) < 0)
        goto error;
P
Prerna Saxena 已提交
596

597 598 599 600
    if (VIR_ALLOC(data) < 0)
        goto error;

    data = nodeData->data.ppc64;
601

602 603 604 605 606
    if (VIR_ALLOC_N(data->pvr, 1) < 0)
        goto error;

    data->len = 1;

607
#if defined(__powerpc__) || defined(__powerpc64__)
J
Jiri Denemark 已提交
608
    asm("mfpvr %0"
609
        : "=r" (data->pvr[0].value));
610
#endif
L
Li Zhang 已提交
611

612 613 614 615 616 617 618
    nodeData->arch = arch;

    return nodeData;

 error:
    ppc64DriverFree(nodeData);
    return NULL;
P
Prerna Saxena 已提交
619 620
}

621
static virCPUCompareResult
622 623 624 625
ppc64DriverGuestData(virCPUDefPtr host,
                     virCPUDefPtr guest,
                     virCPUDataPtr *data,
                     char **message)
626
{
627
    return ppc64Compute(host, guest, data, message);
628 629
}

P
Prerna Saxena 已提交
630
static int
631 632
ppc64DriverUpdate(virCPUDefPtr guest,
                  const virCPUDef *host)
P
Prerna Saxena 已提交
633
{
634
    switch ((virCPUMode) guest->mode) {
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
    case VIR_CPU_MODE_HOST_MODEL:
    case VIR_CPU_MODE_HOST_PASSTHROUGH:
        guest->match = VIR_CPU_MATCH_EXACT;
        virCPUDefFreeModel(guest);
        return virCPUDefCopyModel(guest, host, true);

    case VIR_CPU_MODE_CUSTOM:
        return 0;

    case VIR_CPU_MODE_LAST:
        break;
    }

    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Unexpected CPU mode: %d"), guest->mode);
    return -1;
P
Prerna Saxena 已提交
651
}
652

L
Li Zhang 已提交
653
static virCPUDefPtr
654 655 656 657 658
ppc64DriverBaseline(virCPUDefPtr *cpus,
                    unsigned int ncpus,
                    const char **models ATTRIBUTE_UNUSED,
                    unsigned int nmodels ATTRIBUTE_UNUSED,
                    unsigned int flags)
P
Prerna Saxena 已提交
659
{
660
    struct ppc64_map *map;
661 662
    const struct ppc64_model *model;
    const struct ppc64_vendor *vendor = NULL;
L
Li Zhang 已提交
663
    virCPUDefPtr cpu = NULL;
664
    size_t i;
J
Jiri Denemark 已提交
665

666 667
    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES |
                  VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL);
668

669
    if (!(map = ppc64LoadMap()))
J
Jiri Denemark 已提交
670
        goto error;
L
Li Zhang 已提交
671

672
    if (!(model = ppc64ModelFind(map, cpus[0]->model))) {
J
Jiri Denemark 已提交
673 674
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unknown CPU model %s"), cpus[0]->model);
L
Li Zhang 已提交
675 676 677
        goto error;
    }

J
Jiri Denemark 已提交
678
    for (i = 0; i < ncpus; i++) {
679
        const struct ppc64_vendor *vnd;
680

J
Jiri Denemark 已提交
681 682 683 684 685
        if (STRNEQ(cpus[i]->model, model->name)) {
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("CPUs are incompatible"));
            goto error;
        }
L
Li Zhang 已提交
686

J
Jiri Denemark 已提交
687 688 689
        if (!cpus[i]->vendor)
            continue;

690
        if (!(vnd = ppc64VendorFind(map, cpus[i]->vendor))) {
J
Jiri Denemark 已提交
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
            virReportError(VIR_ERR_OPERATION_FAILED,
                           _("Unknown CPU vendor %s"), cpus[i]->vendor);
            goto error;
        }

        if (model->vendor) {
            if (model->vendor != vnd) {
                virReportError(VIR_ERR_OPERATION_FAILED,
                               _("CPU vendor %s of model %s differs from "
                                 "vendor %s"),
                               model->vendor->name, model->name,
                               vnd->name);
                goto error;
            }
        } else if (vendor) {
            if (vendor != vnd) {
                virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                               _("CPU vendors do not match"));
                goto error;
            }
        } else {
            vendor = vnd;
        }
L
Li Zhang 已提交
714 715
    }

J
Jiri Denemark 已提交
716
    if (VIR_ALLOC(cpu) < 0 ||
717
        VIR_STRDUP(cpu->model, model->name) < 0)
718
        goto error;
L
Li Zhang 已提交
719

720 721
    if (vendor && VIR_STRDUP(cpu->vendor, vendor->name) < 0)
        goto error;
J
Jiri Denemark 已提交
722 723 724

    cpu->type = VIR_CPU_TYPE_GUEST;
    cpu->match = VIR_CPU_MATCH_EXACT;
L
Li Zhang 已提交
725

726
 cleanup:
727
    ppc64MapFree(map);
P
Prerna Saxena 已提交
728

L
Li Zhang 已提交
729
    return cpu;
J
Jiri Denemark 已提交
730

731
 error:
L
Li Zhang 已提交
732 733 734
    virCPUDefFree(cpu);
    cpu = NULL;
    goto cleanup;
P
Prerna Saxena 已提交
735 736
}

737
static int
738
ppc64DriverGetModels(char ***models)
739
{
740 741
    struct ppc64_map *map;
    struct ppc64_model *model;
742 743 744
    char *name;
    size_t nmodels = 0;

745
    if (!(map = ppc64LoadMap()))
746 747 748 749 750 751
        goto error;

    if (models && VIR_ALLOC_N(*models, 0) < 0)
        goto error;

    model = map->models;
752
    while (model) {
753 754 755
        if (models) {
            if (VIR_STRDUP(name, model->name) < 0)
                goto error;
756

757 758 759 760 761
            if (VIR_APPEND_ELEMENT(*models, nmodels, name) < 0)
                goto error;
        } else {
            nmodels++;
        }
762 763 764 765 766

        model = model->next;
    }

 cleanup:
767
    ppc64MapFree(map);
768 769 770 771

    return nmodels;

 error:
772 773 774 775
    if (models) {
        virStringFreeList(*models);
        *models = NULL;
    }
776 777 778 779
    nmodels = -1;
    goto cleanup;
}

780
struct cpuArchDriver cpuDriverPPC64 = {
781 782 783
    .name       = "ppc64",
    .arch       = archs,
    .narch      = ARRAY_CARDINALITY(archs),
784 785
    .compare    = ppc64DriverCompare,
    .decode     = ppc64DriverDecode,
P
Prerna Saxena 已提交
786
    .encode     = NULL,
787 788 789 790 791
    .free       = ppc64DriverFree,
    .nodeData   = ppc64DriverNodeData,
    .guestData  = ppc64DriverGuestData,
    .baseline   = ppc64DriverBaseline,
    .update     = ppc64DriverUpdate,
P
Prerna Saxena 已提交
792
    .hasFeature = NULL,
793
    .getModels  = ppc64DriverGetModels,
P
Prerna Saxena 已提交
794
};