cpu_ppc64.c 16.9 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
    struct cpuPPC64Data 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
};


static void
62
ppc64ModelFree(struct ppc64_model *model)
L
Li Zhang 已提交
63
{
64
    if (!model)
L
Li Zhang 已提交
65 66 67 68 69 70
        return;

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

71 72 73
static struct ppc64_model *
ppc64ModelFind(const struct ppc64_map *map,
               const char *name)
L
Li Zhang 已提交
74
{
75
    struct ppc64_model *model;
L
Li Zhang 已提交
76 77

    model = map->models;
78
    while (model) {
L
Li Zhang 已提交
79 80 81 82 83 84 85 86 87
        if (STREQ(model->name, name))
            return model;

        model = model->next;
    }

    return NULL;
}

88 89 90
static struct ppc64_model *
ppc64ModelFindPVR(const struct ppc64_map *map,
                  uint32_t pvr)
91
{
92
    struct ppc64_model *model;
93 94

    model = map->models;
95
    while (model) {
96 97 98 99 100 101
        if (model->data.pvr == pvr)
            return model;

        model = model->next;
    }

102 103 104
    /* 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 已提交
105
     * If the exact CPU isn't found, return the nearest matching CPU generation
106 107
     */
    if (pvr & 0x0000FFFFul)
108
        return ppc64ModelFindPVR(map, (pvr & 0xFFFF0000ul));
109

110 111 112
    return NULL;
}

113 114
static struct ppc64_model *
ppc64ModelCopy(const struct ppc64_model *model)
115
{
116
    struct ppc64_model *copy;
117 118 119

    if (VIR_ALLOC(copy) < 0 ||
        VIR_STRDUP(copy->name, model->name) < 0) {
120
        ppc64ModelFree(copy);
121 122 123 124 125 126 127 128 129
        return NULL;
    }

    copy->data.pvr = model->data.pvr;
    copy->vendor = model->vendor;

    return copy;
}

130 131 132
static struct ppc64_vendor *
ppc64VendorFind(const struct ppc64_map *map,
                const char *name)
L
Li Zhang 已提交
133
{
134
    struct ppc64_vendor *vendor;
L
Li Zhang 已提交
135 136 137 138 139 140 141 142 143 144 145 146 147

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

        vendor = vendor->next;
    }

    return NULL;
}

static void
148
ppc64VendorFree(struct ppc64_vendor *vendor)
L
Li Zhang 已提交
149 150 151 152 153 154 155 156
{
    if (!vendor)
        return;

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

157 158 159
static struct ppc64_model *
ppc64ModelFromCPU(const virCPUDef *cpu,
                  const struct ppc64_map *map)
160
{
161
    struct ppc64_model *model;
162

163
    if (!(model = ppc64ModelFind(map, cpu->model))) {
164 165 166 167 168
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unknown CPU model %s"), cpu->model);
        goto error;
    }

169
    if (!(model = ppc64ModelCopy(model)))
170 171 172 173
        goto error;

    return model;

174
 error:
175
    ppc64ModelFree(model);
176 177 178 179
    return NULL;
}


L
Li Zhang 已提交
180
static int
181 182
ppc64VendorLoad(xmlXPathContextPtr ctxt,
                struct ppc64_map *map)
L
Li Zhang 已提交
183
{
184
    struct ppc64_vendor *vendor;
L
Li Zhang 已提交
185

186
    if (VIR_ALLOC(vendor) < 0)
187
        return -1;
L
Li Zhang 已提交
188 189 190 191 192 193 194 195

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

196
    if (ppc64VendorFind(map, vendor->name)) {
L
Li Zhang 已提交
197 198 199 200 201
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("CPU vendor %s already defined"), vendor->name);
        goto ignore;
    }

202
    if (!map->vendors) {
L
Li Zhang 已提交
203
        map->vendors = vendor;
204
    } else {
L
Li Zhang 已提交
205 206 207 208
        vendor->next = map->vendors;
        map->vendors = vendor;
    }

209
 cleanup:
210
    return 0;
L
Li Zhang 已提交
211

212
 ignore:
213
    ppc64VendorFree(vendor);
214
    goto cleanup;
L
Li Zhang 已提交
215 216 217
}

static int
218 219
ppc64ModelLoad(xmlXPathContextPtr ctxt,
               struct ppc64_map *map)
L
Li Zhang 已提交
220
{
221
    struct ppc64_model *model;
L
Li Zhang 已提交
222
    char *vendor = NULL;
223
    unsigned long pvr;
L
Li Zhang 已提交
224

225
    if (VIR_ALLOC(model) < 0)
226
        return -1;
L
Li Zhang 已提交
227 228

    model->name = virXPathString("string(@name)", ctxt);
229
    if (!model->name) {
L
Li Zhang 已提交
230 231 232 233 234
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Missing CPU model name"));
        goto ignore;
    }

235
    if (ppc64ModelFind(map, model->name)) {
236 237 238 239
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("CPU model %s already defined"), model->name);
        goto ignore;
    }
L
Li Zhang 已提交
240 241 242 243 244 245 246 247 248 249

    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;
        }

250
        if (!(model->vendor = ppc64VendorFind(map, vendor))) {
L
Li Zhang 已提交
251 252 253 254 255 256 257
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unknown vendor %s referenced by CPU model %s"),
                           vendor, model->name);
            goto ignore;
        }
    }

258 259 260 261 262 263 264 265 266
    if (!virXPathBoolean("boolean(./pvr)", ctxt) ||
        virXPathULongHex("string(./pvr/@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 = pvr;

267
    if (!map->models) {
L
Li Zhang 已提交
268
        map->models = model;
269
    } else {
L
Li Zhang 已提交
270 271 272 273
        model->next = map->models;
        map->models = model;
    }

274
 cleanup:
L
Li Zhang 已提交
275
    VIR_FREE(vendor);
276
    return 0;
L
Li Zhang 已提交
277

278
 ignore:
279
    ppc64ModelFree(model);
280
    goto cleanup;
L
Li Zhang 已提交
281 282 283
}

static int
284 285 286
ppc64MapLoadCallback(cpuMapElement element,
                     xmlXPathContextPtr ctxt,
                     void *data)
L
Li Zhang 已提交
287
{
288
    struct ppc64_map *map = data;
L
Li Zhang 已提交
289 290 291

    switch (element) {
    case CPU_MAP_ELEMENT_VENDOR:
292
        return ppc64VendorLoad(ctxt, map);
L
Li Zhang 已提交
293
    case CPU_MAP_ELEMENT_MODEL:
294
        return ppc64ModelLoad(ctxt, map);
295 296
    case CPU_MAP_ELEMENT_FEATURE:
    case CPU_MAP_ELEMENT_LAST:
L
Li Zhang 已提交
297 298 299 300 301 302 303
        break;
    }

    return 0;
}

static void
304
ppc64MapFree(struct ppc64_map *map)
L
Li Zhang 已提交
305
{
306
    if (!map)
L
Li Zhang 已提交
307 308
        return;

309
    while (map->models) {
310
        struct ppc64_model *model = map->models;
L
Li Zhang 已提交
311
        map->models = model->next;
312
        ppc64ModelFree(model);
L
Li Zhang 已提交
313 314
    }

315
    while (map->vendors) {
316
        struct ppc64_vendor *vendor = map->vendors;
L
Li Zhang 已提交
317
        map->vendors = vendor->next;
318
        ppc64VendorFree(vendor);
L
Li Zhang 已提交
319 320 321 322 323
    }

    VIR_FREE(map);
}

324 325
static struct ppc64_map *
ppc64LoadMap(void)
L
Li Zhang 已提交
326
{
327
    struct ppc64_map *map;
L
Li Zhang 已提交
328

329
    if (VIR_ALLOC(map) < 0)
L
Li Zhang 已提交
330 331
        return NULL;

332
    if (cpuMapLoad("ppc64", ppc64MapLoadCallback, map) < 0)
L
Li Zhang 已提交
333 334 335 336
        goto error;

    return map;

337
 error:
338
    ppc64MapFree(map);
L
Li Zhang 已提交
339 340 341
    return NULL;
}

342
static virCPUDataPtr
343 344
ppc64MakeCPUData(virArch arch,
                 struct cpuPPC64Data *data)
345 346 347 348 349 350 351
{
    virCPUDataPtr cpuData;

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

    cpuData->arch = arch;
352
    cpuData->data.ppc64 = *data;
353 354 355 356 357

    return cpuData;
}

static virCPUCompareResult
358 359 360 361
ppc64Compute(virCPUDefPtr host,
             const virCPUDef *cpu,
             virCPUDataPtr *guestData,
             char **message)
362 363

{
364 365 366
    struct ppc64_map *map = NULL;
    struct ppc64_model *host_model = NULL;
    struct ppc64_model *guest_model = NULL;
367

368
    virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR;
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
    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)
389 390 391 392
                goto cleanup;

            ret = VIR_CPU_COMPARE_INCOMPATIBLE;
            goto cleanup;
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
        }
        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)
408 409 410 411
            goto cleanup;

        ret = VIR_CPU_COMPARE_INCOMPATIBLE;
        goto cleanup;
412 413
    }

414 415 416
    if (!(map = ppc64LoadMap()) ||
        !(host_model = ppc64ModelFromCPU(host, map)) ||
        !(guest_model = ppc64ModelFromCPU(cpu, map)))
417
        goto cleanup;
418

419
    if (guestData) {
420 421 422 423 424 425 426 427 428 429
        if (cpu->type == VIR_CPU_TYPE_GUEST &&
            cpu->match == VIR_CPU_MATCH_STRICT &&
            STRNEQ(guest_model->name, host_model->name)) {
            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)
430 431 432 433
                goto cleanup;

            ret = VIR_CPU_COMPARE_INCOMPATIBLE;
            goto cleanup;
434 435
        }

436
        if (!(*guestData = ppc64MakeCPUData(arch, &guest_model->data)))
437
            goto cleanup;
438 439 440 441
    }

    ret = VIR_CPU_COMPARE_IDENTICAL;

442
 cleanup:
443 444 445
    ppc64MapFree(map);
    ppc64ModelFree(host_model);
    ppc64ModelFree(guest_model);
446 447 448
    return ret;
}

L
Li Zhang 已提交
449
static virCPUCompareResult
450 451 452
ppc64DriverCompare(virCPUDefPtr host,
                   virCPUDefPtr cpu,
                   bool failIncompatible)
L
Li Zhang 已提交
453
{
454 455 456
    if ((cpu->arch == VIR_ARCH_NONE || host->arch == cpu->arch) &&
        STREQ(host->model, cpu->model))
        return VIR_CPU_COMPARE_IDENTICAL;
L
Li Zhang 已提交
457

458 459 460 461 462 463
    if (failIncompatible) {
        virReportError(VIR_ERR_CPU_INCOMPATIBLE, NULL);
        return VIR_CPU_COMPARE_ERROR;
    } else {
        return VIR_CPU_COMPARE_INCOMPATIBLE;
    }
L
Li Zhang 已提交
464 465 466
}

static int
467 468 469 470 471 472
ppc64DriverDecode(virCPUDefPtr cpu,
                  const virCPUData *data,
                  const char **models,
                  unsigned int nmodels,
                  const char *preferred ATTRIBUTE_UNUSED,
                  unsigned int flags)
L
Li Zhang 已提交
473 474
{
    int ret = -1;
475 476
    struct ppc64_map *map;
    const struct ppc64_model *model;
L
Li Zhang 已提交
477

478 479
    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, -1);

480
    if (!data || !(map = ppc64LoadMap()))
L
Li Zhang 已提交
481 482
        return -1;

483
    if (!(model = ppc64ModelFindPVR(map, data->data.ppc64.pvr))) {
484 485
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("Cannot find CPU model with PVR 0x%08x"),
486
                       data->data.ppc64.pvr);
J
Jiri Denemark 已提交
487
        goto cleanup;
488
    }
L
Li Zhang 已提交
489

490
    if (!cpuModelIsAllowed(model->name, models, nmodels)) {
J
Jiri Denemark 已提交
491 492
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("CPU model %s is not supported by hypervisor"),
493
                       model->name);
J
Jiri Denemark 已提交
494
        goto cleanup;
L
Li Zhang 已提交
495 496
    }

497 498
    if (VIR_STRDUP(cpu->model, model->name) < 0 ||
        (model->vendor && VIR_STRDUP(cpu->vendor, model->vendor->name) < 0)) {
499 500
        goto cleanup;
    }
L
Li Zhang 已提交
501 502 503

    ret = 0;

504
 cleanup:
505
    ppc64MapFree(map);
L
Li Zhang 已提交
506 507 508 509 510 511

    return ret;
}


static void
512
ppc64DriverFree(virCPUDataPtr data)
L
Li Zhang 已提交
513
{
514
    if (!data)
L
Li Zhang 已提交
515 516 517 518 519
        return;

    VIR_FREE(data);
}

520
static virCPUDataPtr
521
ppc64DriverNodeData(virArch arch)
P
Prerna Saxena 已提交
522
{
L
Li Zhang 已提交
523
    virCPUDataPtr cpuData;
P
Prerna Saxena 已提交
524

L
Li Zhang 已提交
525
    if (VIR_ALLOC(cpuData) < 0)
P
Prerna Saxena 已提交
526 527
        return NULL;

528 529 530
    cpuData->arch = arch;

#if defined(__powerpc__) || defined(__powerpc64__)
J
Jiri Denemark 已提交
531
    asm("mfpvr %0"
532
        : "=r" (cpuData->data.ppc64.pvr));
533
#endif
L
Li Zhang 已提交
534

L
Li Zhang 已提交
535
    return cpuData;
P
Prerna Saxena 已提交
536 537
}

538
static virCPUCompareResult
539 540 541 542
ppc64DriverGuestData(virCPUDefPtr host,
                     virCPUDefPtr guest,
                     virCPUDataPtr *data,
                     char **message)
543
{
544
    return ppc64Compute(host, guest, data, message);
545 546
}

P
Prerna Saxena 已提交
547
static int
548 549
ppc64DriverUpdate(virCPUDefPtr guest,
                  const virCPUDef *host)
P
Prerna Saxena 已提交
550
{
551
    switch ((virCPUMode) guest->mode) {
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
    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 已提交
568
}
569

L
Li Zhang 已提交
570
static virCPUDefPtr
571 572 573 574 575
ppc64DriverBaseline(virCPUDefPtr *cpus,
                    unsigned int ncpus,
                    const char **models ATTRIBUTE_UNUSED,
                    unsigned int nmodels ATTRIBUTE_UNUSED,
                    unsigned int flags)
P
Prerna Saxena 已提交
576
{
577
    struct ppc64_map *map;
578 579
    const struct ppc64_model *model;
    const struct ppc64_vendor *vendor = NULL;
L
Li Zhang 已提交
580
    virCPUDefPtr cpu = NULL;
581
    size_t i;
J
Jiri Denemark 已提交
582

583 584
    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES |
                  VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL);
585

586
    if (!(map = ppc64LoadMap()))
J
Jiri Denemark 已提交
587
        goto error;
L
Li Zhang 已提交
588

589
    if (!(model = ppc64ModelFind(map, cpus[0]->model))) {
J
Jiri Denemark 已提交
590 591
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unknown CPU model %s"), cpus[0]->model);
L
Li Zhang 已提交
592 593 594
        goto error;
    }

J
Jiri Denemark 已提交
595
    for (i = 0; i < ncpus; i++) {
596
        const struct ppc64_vendor *vnd;
597

J
Jiri Denemark 已提交
598 599 600 601 602
        if (STRNEQ(cpus[i]->model, model->name)) {
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("CPUs are incompatible"));
            goto error;
        }
L
Li Zhang 已提交
603

J
Jiri Denemark 已提交
604 605 606
        if (!cpus[i]->vendor)
            continue;

607
        if (!(vnd = ppc64VendorFind(map, cpus[i]->vendor))) {
J
Jiri Denemark 已提交
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
            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 已提交
631 632
    }

J
Jiri Denemark 已提交
633
    if (VIR_ALLOC(cpu) < 0 ||
634
        VIR_STRDUP(cpu->model, model->name) < 0)
635
        goto error;
L
Li Zhang 已提交
636

637 638
    if (vendor && VIR_STRDUP(cpu->vendor, vendor->name) < 0)
        goto error;
J
Jiri Denemark 已提交
639 640 641

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

643
 cleanup:
644
    ppc64MapFree(map);
P
Prerna Saxena 已提交
645

L
Li Zhang 已提交
646
    return cpu;
J
Jiri Denemark 已提交
647

648
 error:
L
Li Zhang 已提交
649 650 651
    virCPUDefFree(cpu);
    cpu = NULL;
    goto cleanup;
P
Prerna Saxena 已提交
652 653
}

654
static int
655
ppc64DriverGetModels(char ***models)
656
{
657 658
    struct ppc64_map *map;
    struct ppc64_model *model;
659 660 661
    char *name;
    size_t nmodels = 0;

662
    if (!(map = ppc64LoadMap()))
663 664 665 666 667 668
        goto error;

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

    model = map->models;
669
    while (model) {
670 671 672
        if (models) {
            if (VIR_STRDUP(name, model->name) < 0)
                goto error;
673

674 675 676 677 678
            if (VIR_APPEND_ELEMENT(*models, nmodels, name) < 0)
                goto error;
        } else {
            nmodels++;
        }
679 680 681 682 683

        model = model->next;
    }

 cleanup:
684
    ppc64MapFree(map);
685 686 687 688

    return nmodels;

 error:
689 690 691 692
    if (models) {
        virStringFreeList(*models);
        *models = NULL;
    }
693 694 695 696
    nmodels = -1;
    goto cleanup;
}

697
struct cpuArchDriver cpuDriverPPC64 = {
698 699 700
    .name       = "ppc64",
    .arch       = archs,
    .narch      = ARRAY_CARDINALITY(archs),
701 702
    .compare    = ppc64DriverCompare,
    .decode     = ppc64DriverDecode,
P
Prerna Saxena 已提交
703
    .encode     = NULL,
704 705 706 707 708
    .free       = ppc64DriverFree,
    .nodeData   = ppc64DriverNodeData,
    .guestData  = ppc64DriverGuestData,
    .baseline   = ppc64DriverBaseline,
    .update     = ppc64DriverUpdate,
P
Prerna Saxena 已提交
709
    .hasFeature = NULL,
710
    .getModels  = ppc64DriverGetModels,
P
Prerna Saxena 已提交
711
};