testutilsqemu.c 18.2 KB
Newer Older
1
#include <config.h>
A
Atsushi SAKAI 已提交
2
#ifdef WITH_QEMU
3
# include <stdlib.h>
4

5 6
# include "testutilsqemu.h"
# include "testutils.h"
7
# include "viralloc.h"
J
Jiri Denemark 已提交
8
# include "cpu_conf.h"
9
# include "qemu/qemu_driver.h"
10
# include "qemu/qemu_domain.h"
11 12
# define __QEMU_CAPSRIV_H_ALLOW__
# include "qemu/qemu_capspriv.h"
13 14 15
# include "virstring.h"

# define VIR_FROM_THIS VIR_FROM_QEMU
16

17 18
virCPUDefPtr cpuDefault;
virCPUDefPtr cpuHaswell;
19
virCPUDefPtr cpuPower8;
20 21

static virCPUFeatureDef cpuDefaultFeatures[] = {
22
    { (char *) "ds",        -1 },
23
    { (char *) "acpi",      -1 },
24 25 26 27 28 29 30 31 32 33 34
    { (char *) "ss",        -1 },
    { (char *) "ht",        -1 },
    { (char *) "tm",        -1 },
    { (char *) "pbe",       -1 },
    { (char *) "ds_cpl",    -1 },
    { (char *) "vmx",       -1 },
    { (char *) "est",       -1 },
    { (char *) "tm2",       -1 },
    { (char *) "cx16",      -1 },
    { (char *) "xtpr",      -1 },
    { (char *) "lahf_lm",   -1 },
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
};
static virCPUDef cpuDefaultData = {
    VIR_CPU_TYPE_HOST,      /* type */
    0,                      /* mode */
    0,                      /* match */
    VIR_ARCH_X86_64,        /* arch */
    (char *) "core2duo",    /* model */
    NULL,                   /* vendor_id */
    0,                      /* fallback */
    (char *) "Intel",       /* vendor */
    1,                      /* sockets */
    2,                      /* cores */
    1,                      /* threads */
    ARRAY_CARDINALITY(cpuDefaultFeatures), /* nfeatures */
    ARRAY_CARDINALITY(cpuDefaultFeatures), /* nfeatures_max */
    cpuDefaultFeatures,     /* features */
};

static virCPUFeatureDef cpuHaswellFeatures[] = {
    { (char *) "vme",       -1 },
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
    { (char *) "ds",        -1 },
    { (char *) "acpi",      -1 },
    { (char *) "ss",        -1 },
    { (char *) "ht",        -1 },
    { (char *) "tm",        -1 },
    { (char *) "pbe",       -1 },
    { (char *) "dtes64",    -1 },
    { (char *) "monitor",   -1 },
    { (char *) "ds_cpl",    -1 },
    { (char *) "vmx",       -1 },
    { (char *) "smx",       -1 },
    { (char *) "est",       -1 },
    { (char *) "tm2",       -1 },
    { (char *) "xtpr",      -1 },
    { (char *) "pdcm",      -1 },
    { (char *) "osxsave",   -1 },
    { (char *) "f16c",      -1 },
    { (char *) "rdrand",    -1 },
    { (char *) "cmt",       -1 },
    { (char *) "pdpe1gb",   -1 },
    { (char *) "abm",       -1 },
    { (char *) "invtsc",    -1 },
    { (char *) "lahf_lm",   -1 },
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
};
static virCPUDef cpuHaswellData = {
    VIR_CPU_TYPE_HOST,      /* type */
    0,                      /* mode */
    0,                      /* match */
    VIR_ARCH_X86_64,        /* arch */
    (char *) "Haswell",     /* model */
    NULL,                   /* vendor_id */
    0,                      /* fallback */
    (char *) "Intel",       /* vendor */
    1,                      /* sockets */
    2,                      /* cores */
    2,                      /* threads */
    ARRAY_CARDINALITY(cpuHaswellFeatures), /* nfeatures */
    ARRAY_CARDINALITY(cpuHaswellFeatures), /* nfeatures_max */
    cpuHaswellFeatures,     /* features */
};

96 97 98 99 100 101 102 103 104
static virCPUDef cpuPower8Data = {
    .type = VIR_CPU_TYPE_HOST,
    .arch = VIR_ARCH_PPC64,
    .model = (char *) "POWER8",
    .sockets = 1,
    .cores = 8,
    .threads = 8,
};

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
static virCapsGuestMachinePtr *testQemuAllocMachines(int *nmachines)
{
    virCapsGuestMachinePtr *machines;
    static const char *const x86_machines[] = {
        "pc", "isapc"
    };

    machines = virCapabilitiesAllocMachines(x86_machines,
                                            ARRAY_CARDINALITY(x86_machines));
    if (machines == NULL)
        return NULL;

    *nmachines = ARRAY_CARDINALITY(x86_machines);

    return machines;
}

M
Mark McLoughlin 已提交
122 123 124 125 126 127 128 129 130 131 132 133
/* Newer versions of qemu have versioned machine types to allow
 * compatibility with older releases.
 * The 'pc' machine type is an alias of the newest machine type.
 */
static virCapsGuestMachinePtr *testQemuAllocNewerMachines(int *nmachines)
{
    virCapsGuestMachinePtr *machines;
    char *canonical;
    static const char *const x86_machines[] = {
        "pc-0.11", "pc", "pc-0.10", "isapc"
    };

134
    if (VIR_STRDUP(canonical, x86_machines[0]) < 0)
M
Mark McLoughlin 已提交
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
        return NULL;

    machines = virCapabilitiesAllocMachines(x86_machines,
                                            ARRAY_CARDINALITY(x86_machines));
    if (machines == NULL) {
        VIR_FREE(canonical);
        return NULL;
    }

    machines[1]->canonical = canonical;

    *nmachines = ARRAY_CARDINALITY(x86_machines);

    return machines;
}

151

152 153 154 155 156 157 158 159 160 161
static int testQemuAddPPC64Guest(virCapsPtr caps)
{
    static const char *machine[] = { "pseries" };
    virCapsGuestMachinePtr *machines = NULL;
    virCapsGuestPtr guest;

    machines = virCapabilitiesAllocMachines(machine, 1);
    if (!machines)
        goto error;

162
    guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_PPC64,
163 164 165 166 167
                                    "/usr/bin/qemu-system-ppc64", NULL,
                                     1, machines);
    if (!guest)
        goto error;

168
    if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU, NULL, NULL, 0, NULL))
169 170 171 172
        goto error;

    return 0;

173
 error:
174 175 176 177 178
    /* No way to free a guest? */
    virCapabilitiesFreeMachines(machines, 1);
    return -1;
}

179 180 181 182 183 184 185 186 187 188
static int testQemuAddPPC64LEGuest(virCapsPtr caps)
{
    static const char *machine[] = { "pseries" };
    virCapsGuestMachinePtr *machines = NULL;
    virCapsGuestPtr guest;

    machines = virCapabilitiesAllocMachines(machine, 1);
    if (!machines)
        goto error;

189
    guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_PPC64LE,
190 191 192 193 194
                                    "/usr/bin/qemu-system-ppc64", NULL,
                                     1, machines);
    if (!guest)
        goto error;

195
    if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU, NULL, NULL, 0, NULL))
196 197 198 199 200 201 202 203 204 205
        goto error;

    return 0;

 error:
    /* No way to free a guest? */
    virCapabilitiesFreeMachines(machines, 1);
    return -1;
}

O
Olivia Yin 已提交
206 207 208 209 210
static int testQemuAddPPCGuest(virCapsPtr caps)
{
    static const char *machine[] = { "g3beige",
                                     "mac99",
                                     "prep",
211
                                     "ppce500" };
O
Olivia Yin 已提交
212 213 214 215 216 217 218
    virCapsGuestMachinePtr *machines = NULL;
    virCapsGuestPtr guest;

    machines = virCapabilitiesAllocMachines(machine, 1);
    if (!machines)
        goto error;

219
    guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_PPC,
O
Olivia Yin 已提交
220 221 222 223 224
                                    "/usr/bin/qemu-system-ppc", NULL,
                                     1, machines);
    if (!guest)
        goto error;

225
    if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU, NULL, NULL, 0, NULL))
O
Olivia Yin 已提交
226 227 228 229
        goto error;

    return 0;

230
 error:
O
Olivia Yin 已提交
231 232 233 234 235
    /* No way to free a guest? */
    virCapabilitiesFreeMachines(machines, 1);
    return -1;
}

236 237
static int testQemuAddS390Guest(virCapsPtr caps)
{
238 239
    static const char *s390_machines[] = { "s390-virtio",
                                           "s390-ccw-virtio" };
240 241 242 243 244 245 246 247
    virCapsGuestMachinePtr *machines = NULL;
    virCapsGuestPtr guest;

    machines = virCapabilitiesAllocMachines(s390_machines,
                                            ARRAY_CARDINALITY(s390_machines));
    if (!machines)
        goto error;

248
    guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_S390X,
249 250 251 252 253 254
                                    "/usr/bin/qemu-system-s390x", NULL,
                                    ARRAY_CARDINALITY(s390_machines),
                                    machines);
    if (!guest)
        goto error;

255
    if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU, NULL, NULL, 0, NULL))
256 257 258 259
        goto error;

    return 0;

260
 error:
261 262 263 264
    virCapabilitiesFreeMachines(machines, ARRAY_CARDINALITY(s390_machines));
    return -1;
}

265 266 267 268 269 270 271 272 273 274 275 276 277
static int testQemuAddArmGuest(virCapsPtr caps)
{
    static const char *machines[] = { "vexpress-a9",
                                      "vexpress-a15",
                                      "versatilepb" };
    virCapsGuestMachinePtr *capsmachines = NULL;
    virCapsGuestPtr guest;

    capsmachines = virCapabilitiesAllocMachines(machines,
                                                ARRAY_CARDINALITY(machines));
    if (!capsmachines)
        goto error;

278
    guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_ARMV7L,
279 280 281 282 283 284
                                    "/usr/bin/qemu-system-arm", NULL,
                                    ARRAY_CARDINALITY(machines),
                                    capsmachines);
    if (!guest)
        goto error;

285
    if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU, NULL, NULL, 0, NULL))
286 287 288 289
        goto error;

    return 0;

290
 error:
291 292 293 294
    virCapabilitiesFreeMachines(capsmachines, ARRAY_CARDINALITY(machines));
    return -1;
}

295 296 297 298 299 300 301 302 303 304 305
static int testQemuAddAARCH64Guest(virCapsPtr caps)
{
    static const char *machines[] = { "virt"};
    virCapsGuestMachinePtr *capsmachines = NULL;
    virCapsGuestPtr guest;

    capsmachines = virCapabilitiesAllocMachines(machines,
                                                ARRAY_CARDINALITY(machines));
    if (!capsmachines)
        goto error;

306
    guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_AARCH64,
307 308 309 310 311 312
                                    "/usr/bin/qemu-system-aarch64", NULL,
                                    ARRAY_CARDINALITY(machines),
                                    capsmachines);
    if (!guest)
        goto error;

313
    if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU, NULL, NULL, 0, NULL))
314 315 316 317
        goto error;

    return 0;

318
 error:
319 320 321
    virCapabilitiesFreeMachines(capsmachines, ARRAY_CARDINALITY(machines));
    return -1;
}
322

323 324
virCapsPtr testQemuCapsInit(void)
{
325 326
    virCapsPtr caps;
    virCapsGuestPtr guest;
327 328
    virCapsGuestMachinePtr *machines = NULL;
    int nmachines = 0;
329

330
    if (!(caps = virCapabilitiesNew(VIR_ARCH_X86_64, false, false)))
331 332
        return NULL;

333 334 335 336 337 338 339 340 341 342
    /* Add dummy 'none' security_driver. This is equal to setting
     * security_driver = "none" in qemu.conf. */
    if (VIR_ALLOC_N(caps->host.secModels, 1) < 0)
        goto cleanup;
    caps->host.nsecModels = 1;

    if (VIR_STRDUP(caps->host.secModels[0].model, "none") < 0 ||
        VIR_STRDUP(caps->host.secModels[0].doi, "0") < 0)
        goto cleanup;

343
    if (!(cpuDefault = virCPUDefCopy(&cpuDefaultData)) ||
344 345
        !(cpuHaswell = virCPUDefCopy(&cpuHaswellData)) ||
        !(cpuPower8 = virCPUDefCopy(&cpuPower8Data)))
346 347
        goto cleanup;

348
    qemuTestSetHostCPU(caps, NULL);
349

350 351
    caps->host.nnumaCell_max = 4;

352
    if ((machines = testQemuAllocMachines(&nmachines)) == NULL)
353 354
        goto cleanup;

355
    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_I686,
356
                                         "/usr/bin/qemu", NULL,
357
                                         nmachines, machines)) == NULL ||
358
        !virCapabilitiesAddGuestFeature(guest, "cpuselection", true, false))
359
        goto cleanup;
360 361
    machines = NULL;

362
    if (virCapabilitiesAddGuestDomain(guest,
363
                                      VIR_DOMAIN_VIRT_QEMU,
364 365 366 367 368 369
                                      NULL,
                                      NULL,
                                      0,
                                      NULL) == NULL)
        goto cleanup;

370 371 372 373 374 375 376 377 378 379 380 381
    if ((machines = testQemuAllocMachines(&nmachines)) == NULL)
        goto cleanup;

    if (virCapabilitiesAddGuestDomain(guest,
                                      VIR_DOMAIN_VIRT_KVM,
                                      "/usr/bin/qemu-kvm",
                                      NULL,
                                      nmachines,
                                      machines) == NULL)
        goto cleanup;
    machines = NULL;

M
Mark McLoughlin 已提交
382
    if ((machines = testQemuAllocNewerMachines(&nmachines)) == NULL)
383 384
        goto cleanup;

385
    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_X86_64,
386
                                         "/usr/bin/qemu-system-x86_64", NULL,
387
                                         nmachines, machines)) == NULL ||
388
        !virCapabilitiesAddGuestFeature(guest, "cpuselection", true, false))
389
        goto cleanup;
390 391
    machines = NULL;

392
    if (virCapabilitiesAddGuestDomain(guest,
393
                                      VIR_DOMAIN_VIRT_QEMU,
394 395 396 397 398
                                      NULL,
                                      NULL,
                                      0,
                                      NULL) == NULL)
        goto cleanup;
399 400 401 402

    if ((machines = testQemuAllocMachines(&nmachines)) == NULL)
        goto cleanup;

403
    if (virCapabilitiesAddGuestDomain(guest,
404
                                      VIR_DOMAIN_VIRT_KVM,
405 406
                                      "/usr/bin/kvm",
                                      NULL,
407 408
                                      nmachines,
                                      machines) == NULL)
409
        goto cleanup;
410
    machines = NULL;
411 412

    if (virCapabilitiesAddGuestDomain(guest,
413
                                      VIR_DOMAIN_VIRT_KVM,
414 415 416 417 418 419
                                      "/usr/bin/kvm",
                                      NULL,
                                      0,
                                      NULL) == NULL)
        goto cleanup;

420 421 422
    if (testQemuAddPPC64Guest(caps))
        goto cleanup;

423 424 425
    if (testQemuAddPPC64LEGuest(caps))
        goto cleanup;

O
Olivia Yin 已提交
426 427 428
    if (testQemuAddPPCGuest(caps))
        goto cleanup;

429 430 431
    if (testQemuAddS390Guest(caps))
        goto cleanup;

432 433 434
    if (testQemuAddArmGuest(caps))
        goto cleanup;

435 436 437
    if (testQemuAddAARCH64Guest(caps))
        goto cleanup;

438
    if (virTestGetDebug()) {
439 440 441 442 443 444
        char *caps_str;

        caps_str = virCapabilitiesFormatXML(caps);
        if (!caps_str)
            goto cleanup;

445
        VIR_TEST_DEBUG("QEMU driver capabilities:\n%s", caps_str);
446 447 448 449

        VIR_FREE(caps_str);
    }

450 451
    return caps;

452
 cleanup:
453
    virCapabilitiesFreeMachines(machines, nmachines);
454 455 456
    caps->host.cpu = NULL;
    virCPUDefFree(cpuDefault);
    virCPUDefFree(cpuHaswell);
457
    virCPUDefFree(cpuPower8);
458
    virObjectUnref(caps);
459 460
    return NULL;
}
461 462


463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
void
qemuTestSetHostArch(virCapsPtr caps,
                    virArch arch)
{
    if (arch == VIR_ARCH_NONE)
        arch = VIR_ARCH_X86_64;
    caps->host.arch = arch;
    qemuTestSetHostCPU(caps, NULL);
}


void
qemuTestSetHostCPU(virCapsPtr caps,
                   virCPUDefPtr cpu)
{
    virArch arch = caps->host.arch;

    if (!cpu) {
        if (ARCH_IS_X86(arch))
            cpu = cpuDefault;
483 484
        else if (ARCH_IS_PPC64(arch))
            cpu = cpuPower8;
485 486 487 488 489 490 491 492
    }

    if (cpu)
        caps->host.arch = cpu->arch;
    caps->host.cpu = cpu;
}


493
virQEMUCapsPtr
494 495
qemuTestParseCapabilities(virCapsPtr caps,
                          const char *capsFile)
496 497
{
    virQEMUCapsPtr qemuCaps = NULL;
498 499 500
    time_t qemuctime;
    time_t selfctime;
    unsigned long version;
501

502
    if (!(qemuCaps = virQEMUCapsNew()) ||
503
        virQEMUCapsLoadCache(caps, qemuCaps, capsFile,
504
                             &qemuctime, &selfctime, &version) < 0)
505 506 507 508 509 510 511 512
        goto error;

    return qemuCaps;

 error:
    virObjectUnref(qemuCaps);
    return NULL;
}
513 514 515

void qemuTestDriverFree(virQEMUDriver *driver)
{
516
    virMutexDestroy(&driver->lock);
517
    virQEMUCapsCacheFree(driver->qemuCapsCache);
518 519 520
    virObjectUnref(driver->xmlopt);
    virObjectUnref(driver->caps);
    virObjectUnref(driver->config);
521
    virObjectUnref(driver->securityManager);
522 523
}

524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
int qemuTestCapsCacheInsert(virQEMUCapsCachePtr cache, const char *binary,
                            virQEMUCapsPtr caps)
{
    int ret;

    if (caps) {
        /* Our caps were created artificially, so we don't want
         * virQEMUCapsCacheFree() to attempt to deallocate them */
        virObjectRef(caps);
    } else {
        caps = virQEMUCapsNew();
        if (!caps)
            return -ENOMEM;
    }

    /* We can have repeating names for our test data sets,
     * so make sure there's no old copy */
    virHashRemoveEntry(cache->binaries, binary);

    ret = virHashAddEntry(cache->binaries, binary, caps);
    if (ret < 0)
        virObjectUnref(caps);
P
Pavel Fedin 已提交
546 547
    else
        qemuTestCapsName = binary;
548 549 550 551

    return ret;
}

552 553
int qemuTestDriverInit(virQEMUDriver *driver)
{
554 555
    virSecurityManagerPtr mgr = NULL;

556 557
    memset(driver, 0, sizeof(*driver));

558 559 560
    if (virMutexInit(&driver->lock) < 0)
        return -1;

561 562
    driver->config = virQEMUDriverConfigNew(false);
    if (!driver->config)
563
        goto error;
564

565 566 567 568 569 570 571
    /* Overwrite some default paths so it's consistent for tests. */
    VIR_FREE(driver->config->libDir);
    VIR_FREE(driver->config->channelTargetDir);
    if (VIR_STRDUP(driver->config->libDir, "/tmp/lib") < 0 ||
        VIR_STRDUP(driver->config->channelTargetDir, "/tmp/channel") < 0)
        goto error;

572 573 574 575
    driver->caps = testQemuCapsInit();
    if (!driver->caps)
        goto error;

P
Pavel Fedin 已提交
576 577 578 579 580 581
    /* Using /dev/null for libDir and cacheDir automatically produces errors
     * upon attempt to use any of them */
    driver->qemuCapsCache = virQEMUCapsCacheNew("/dev/null", "/dev/null", 0, 0);
    if (!driver->qemuCapsCache)
        goto error;

582 583 584 585
    driver->xmlopt = virQEMUDriverCreateXMLConf(driver);
    if (!driver->xmlopt)
        goto error;

P
Pavel Fedin 已提交
586 587 588
    if (qemuTestCapsCacheInsert(driver->qemuCapsCache, "empty", NULL) < 0)
        goto error;

589 590 591 592 593 594
    if (!(mgr = virSecurityManagerNew("none", "qemu",
                                      VIR_SECURITY_MANAGER_PRIVILEGED)))
        goto error;
    if (!(driver->securityManager = virSecurityManagerNewStack(mgr)))
        goto error;

595 596 597
    return 0;

 error:
598
    virObjectUnref(mgr);
599 600 601
    qemuTestDriverFree(driver);
    return -1;
}
602

603 604 605 606 607 608 609 610 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 636 637 638
int
testQemuCapsSetGIC(virQEMUCapsPtr qemuCaps,
                   int gic)
{
    virGICCapability *gicCapabilities = NULL;
    size_t ngicCapabilities = 0;
    int ret = -1;

    if (VIR_ALLOC_N(gicCapabilities, 2) < 0)
        goto out;

# define IMPL_BOTH \
         VIR_GIC_IMPLEMENTATION_KERNEL|VIR_GIC_IMPLEMENTATION_EMULATED

    if (gic & GIC_V2) {
        gicCapabilities[ngicCapabilities].version = VIR_GIC_VERSION_2;
        gicCapabilities[ngicCapabilities].implementation = IMPL_BOTH;
        ngicCapabilities++;
    }
    if (gic & GIC_V3) {
        gicCapabilities[ngicCapabilities].version = VIR_GIC_VERSION_3;
        gicCapabilities[ngicCapabilities].implementation = IMPL_BOTH;
        ngicCapabilities++;
    }

# undef IMPL_BOTH

    virQEMUCapsSetGICCapabilities(qemuCaps,
                                  gicCapabilities, ngicCapabilities);

    ret = 0;

 out:
    return ret;
}

A
Atsushi SAKAI 已提交
639
#endif