virCapsPtr libxlMakeCapabilities(libxl_ctx *ctx) { virCapsPtr caps; #ifdef LIBXL_HAVE_NO_SUSPEND_RESUME if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL) #else if ((caps = virCapabilitiesNew(virArchFromHost(), true, true)) == NULL) #endif return NULL; if (libxlCapsInitHost(ctx, caps) < 0) goto error; if (libxlCapsInitNuma(ctx, caps) < 0) goto error; if (libxlCapsInitGuests(ctx, caps) < 0) goto error; return caps; error: virObjectUnref(caps); return NULL; }
virCapsPtr openvzCapsInit(void) { virCapsPtr caps; virCapsGuestPtr guest; if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL) goto no_memory; if (nodeCapsInitNUMA(caps) < 0) goto no_memory; if ((guest = virCapabilitiesAddGuest(caps, "exe", caps->host.arch, NULL, NULL, 0, NULL)) == NULL) goto no_memory; if (virCapabilitiesAddGuestDomain(guest, "openvz", NULL, NULL, 0, NULL) == NULL) goto no_memory; return caps; no_memory: virObjectUnref(caps); return NULL; }
virCapsPtr virBhyveCapsBuild(void) { virCapsPtr caps; virCapsGuestPtr guest; if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL) return NULL; if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_X86_64, "bhyve", NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_BHYVE, NULL, NULL, 0, NULL) == NULL) goto error; if (virBhyveCapsInitCPU(caps, virArchFromHost()) < 0) VIR_WARN("Failed to get host CPU: %s", virGetLastErrorMessage()); return caps; error: virObjectUnref(caps); return NULL; }
virCapsPtr openvzCapsInit(void) { virCapsPtr caps; virCapsGuestPtr guest; if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL) goto no_memory; if (nodeCapsInitNUMA(NULL, caps) < 0) goto no_memory; if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_EXE, caps->host.arch, NULL, NULL, 0, NULL)) == NULL) goto no_memory; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_OPENVZ, NULL, NULL, 0, NULL) == NULL) goto no_memory; return caps; no_memory: virObjectUnref(caps); return NULL; }
static virCapsPtr testGetCaps(char *capsData, const testQemuData *data) { virQEMUCapsPtr qemuCaps = NULL; virCapsPtr caps = NULL; if ((qemuCaps = testQemuGetCaps(capsData)) == NULL) { fprintf(stderr, "failed to parse qemu capabilities flags"); goto error; } if ((caps = virCapabilitiesNew(data->guestarch, false, false)) == NULL) { fprintf(stderr, "failed to create the fake capabilities"); goto error; } if (virQEMUCapsInitGuestFromBinary(caps, "/usr/bin/qemu-system-i386", qemuCaps, "/usr/bin/qemu-system-i386", qemuCaps, data->guestarch) < 0) { fprintf(stderr, "failed to create the capabilities from qemu"); goto error; } virObjectUnref(qemuCaps); return caps; error: virObjectUnref(qemuCaps); return NULL; }
static virCapsPtr vzBuildCapabilities(void) { virCapsPtr caps = NULL; virCPUDefPtr cpu = NULL; virCPUDataPtr data = NULL; virNodeInfo nodeinfo; virDomainOSType ostypes[] = { VIR_DOMAIN_OSTYPE_HVM, VIR_DOMAIN_OSTYPE_EXE }; virArch archs[] = { VIR_ARCH_I686, VIR_ARCH_X86_64 }; const char *const emulators[] = { "parallels", "vz" }; virDomainVirtType virt_types[] = { VIR_DOMAIN_VIRT_PARALLELS, VIR_DOMAIN_VIRT_VZ }; size_t i, j, k; if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL) return NULL; if (nodeCapsInitNUMA(NULL, caps) < 0) goto error; for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) for (k = 0; k < 2; k++) if (vzCapsAddGuestDomain(caps, ostypes[i], archs[j], emulators[k], virt_types[k]) < 0) goto error; if (nodeGetInfo(NULL, &nodeinfo)) goto error; if (VIR_ALLOC(cpu) < 0) goto error; cpu->arch = caps->host.arch; cpu->type = VIR_CPU_TYPE_HOST; cpu->sockets = nodeinfo.sockets; cpu->cores = nodeinfo.cores; cpu->threads = nodeinfo.threads; caps->host.cpu = cpu; if (!(data = cpuNodeData(cpu->arch)) || cpuDecode(cpu, data, NULL, 0, NULL) < 0) { goto cleanup; } cleanup: cpuDataFree(data); return caps; error: virObjectUnref(caps); goto cleanup; }
static int test_virCapabilities(const void *opaque) { struct virCapabilitiesData *data = (struct virCapabilitiesData *) opaque; const char *archStr = virArchToString(data->arch); virCapsPtr caps = NULL; char *capsXML = NULL; char *path = NULL; char *dir = NULL; char *resctrl = NULL; int ret = -1; /* * We want to keep our directory structure clean, so if there's both resctrl * and system used, we need to use slightly different path; a subdir. */ if (virAsprintf(&dir, "%s/vircaps2xmldata/linux-%s%s", abs_srcdir, data->filename, data->resctrl ? "/system" : "") < 0) goto cleanup; if (virAsprintf(&resctrl, "%s/vircaps2xmldata/linux-%s/resctrl", abs_srcdir, data->filename) < 0) goto cleanup; virFileWrapperAddPrefix("/sys/devices/system", dir); virFileWrapperAddPrefix("/sys/fs/resctrl", resctrl); caps = virCapabilitiesNew(data->arch, data->offlineMigrate, data->liveMigrate); if (!caps) goto cleanup; if (virCapabilitiesInitNUMA(caps) < 0 || virCapabilitiesInitCaches(caps) < 0) goto cleanup; virFileWrapperClearPrefixes(); if (!(capsXML = virCapabilitiesFormatXML(caps))) goto cleanup; if (virAsprintf(&path, "%s/vircaps2xmldata/vircaps-%s-%s.xml", abs_srcdir, archStr, data->filename) < 0) goto cleanup; if (virTestCompareToFile(capsXML, path) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(dir); VIR_FREE(resctrl); VIR_FREE(path); VIR_FREE(capsXML); virObjectUnref(caps); return ret; }
virCapsPtr umlCapsInit(void) { struct utsname utsname; virCapsPtr caps; virCapsGuestPtr guest; /* Really, this never fails - look at the man-page. */ uname (&utsname); if ((caps = virCapabilitiesNew(utsname.machine, 0, 0)) == NULL) goto error; /* Some machines have problematic NUMA toplogy causing * unexpected failures. We don't want to break the QEMU * driver in this scenario, so log errors & carry on */ if (nodeCapsInitNUMA(caps) < 0) { virCapabilitiesFreeNUMAInfo(caps); VIR_WARN("Failed to query host NUMA topology, disabling NUMA capabilities"); } if (virGetHostUUID(caps->host.host_uuid)) { umlReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot get the host uuid")); goto error; } if ((guest = virCapabilitiesAddGuest(caps, "uml", utsname.machine, STREQ(utsname.machine, "x86_64") ? 64 : 32, NULL, NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, "uml", NULL, NULL, 0, NULL) == NULL) goto error; caps->defaultConsoleTargetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_UML; return caps; error: virCapabilitiesFree(caps); return NULL; }
static void testCapsInit(void) { virCapsGuestPtr guest = NULL; caps = virCapabilitiesNew("i686", 1, 1); if (caps == NULL) { return; } virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x0c, 0x29 });
virCapsPtr umlCapsInit(void) { virCapsPtr caps; virCapsGuestPtr guest; if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL) goto error; /* Some machines have problematic NUMA toplogy causing * unexpected failures. We don't want to break the QEMU * driver in this scenario, so log errors & carry on */ if (virCapabilitiesInitNUMA(caps) < 0) { virCapabilitiesFreeNUMAInfo(caps); VIR_WARN("Failed to query host NUMA topology, disabling NUMA capabilities"); } if (virCapabilitiesInitCaches(caps) < 0) VIR_WARN("Failed to get host CPU cache info"); if (virNodeSuspendGetTargetMask(&caps->host.powerMgmt) < 0) VIR_WARN("Failed to get host power management capabilities"); if (virGetHostUUID(caps->host.host_uuid)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot get the host uuid")); goto error; } if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_UML, caps->host.arch, NULL, NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_UML, NULL, NULL, 0, NULL) == NULL) goto error; return caps; error: virObjectUnref(caps); return NULL; }
static virCapsPtr libxlBuildCapabilities(const char *hostmachine, int host_pae, struct guest_arch *guest_archs, int nr_guest_archs) { virCapsPtr caps; int i; if ((caps = virCapabilitiesNew(hostmachine, 1, 1)) == NULL) goto no_memory; virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x16, 0x3e });
static void testCapsInit(void) { virCapsGuestPtr guest = NULL; caps = virCapabilitiesNew(VIR_ARCH_I686, 1, 1); if (caps == NULL) { return; } virCapabilitiesAddHostMigrateTransport(caps, "esx"); /* i686 guest */ guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_I686, NULL, NULL, 0, NULL); if (guest == NULL) { goto failure; } if (virCapabilitiesAddGuestDomain(guest, "vmware", NULL, NULL, 0, NULL) == NULL) { goto failure; } /* x86_64 guest */ guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_X86_64, NULL, NULL, 0, NULL); if (guest == NULL) { goto failure; } if (virCapabilitiesAddGuestDomain(guest, "vmware", NULL, NULL, 0, NULL) == NULL) { goto failure; } return; failure: virObjectUnref(caps); virObjectUnref(xmlopt); caps = NULL; }
virCapsPtr virStorageBackendGetCapabilities(void) { virCapsPtr caps; size_t i; if (!(caps = virCapabilitiesNew(VIR_ARCH_NONE, false, false))) return NULL; for (i = 0; i < virStorageBackendsCount; i++) virCapabilitiesAddStoragePool(caps, virStorageBackends[i]->type); return caps; }
virCapsPtr qemuCapsInit(virCapsPtr old_caps) { struct utsname utsname; virCapsPtr caps; int i; char *xenner = NULL; /* Really, this never fails - look at the man-page. */ uname (&utsname); if ((caps = virCapabilitiesNew(utsname.machine, 1, 1)) == NULL) goto no_memory; /* Using KVM's mac prefix for QEMU too */ virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x52, 0x54, 0x00 });
static void testCapsInit(void) { virCapsGuestPtr guest = NULL; caps = virCapabilitiesNew(VIR_ARCH_I686, true, true); if (caps == NULL) return; virCapabilitiesAddHostMigrateTransport(caps, "esx"); /* i686 guest */ guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_I686, NULL, NULL, 0, NULL); if (guest == NULL) goto failure; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_VMWARE, NULL, NULL, 0, NULL) == NULL) { goto failure; } /* x86_64 guest */ guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_X86_64, NULL, NULL, 0, NULL); if (guest == NULL) goto failure; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_VMWARE, NULL, NULL, 0, NULL) == NULL) { goto failure; } return; failure: virObjectUnref(caps); caps = NULL; }
/* * Build NUMA Toplogy with cell id starting from (0 + seq) * for testing */ static virCapsPtr buildNUMATopology(int seq) { virCapsPtr caps; virCapsHostNUMACellCPUPtr cell_cpus = NULL; int core_id, cell_id; int id; if ((caps = virCapabilitiesNew(VIR_ARCH_X86_64, false, false)) == NULL) goto error; id = 0; for (cell_id = 0; cell_id < MAX_CELLS; cell_id++) { if (VIR_ALLOC_N(cell_cpus, MAX_CPUS_IN_CELL) < 0) goto error; for (core_id = 0; core_id < MAX_CPUS_IN_CELL; core_id++) { cell_cpus[core_id].id = id + core_id; cell_cpus[core_id].socket_id = cell_id + seq; cell_cpus[core_id].core_id = id + core_id; if (!(cell_cpus[core_id].siblings = virBitmapNew(MAX_CPUS_IN_CELL))) goto error; ignore_value(virBitmapSetBit(cell_cpus[core_id].siblings, id)); } id++; if (virCapabilitiesAddHostNUMACell(caps, cell_id + seq, MAX_MEM_IN_CELL, MAX_CPUS_IN_CELL, cell_cpus, VIR_ARCH_NONE, NULL, VIR_ARCH_NONE, NULL) < 0) goto error; cell_cpus = NULL; } return caps; error: virCapabilitiesClearHostNUMACellCPUTopology(cell_cpus, MAX_CPUS_IN_CELL); VIR_FREE(cell_cpus); virObjectUnref(caps); return NULL; }
static int testQemuCapsCopy(const void *opaque) { int ret = -1; const testQemuData *data = opaque; char *capsFile = NULL; virCapsPtr caps = NULL; virQEMUCapsPtr orig = NULL; virQEMUCapsPtr copy = NULL; char *actual = NULL; if (virAsprintf(&capsFile, "%s/qemucapabilitiesdata/%s.%s.xml", abs_srcdir, data->base, data->archName) < 0) goto cleanup; if (!(caps = virCapabilitiesNew(virArchFromString(data->archName), false, false))) goto cleanup; if (!(orig = qemuTestParseCapabilities(caps, capsFile))) goto cleanup; if (!(copy = virQEMUCapsNewCopy(orig))) goto cleanup; if (!(actual = virQEMUCapsFormatCache(copy))) goto cleanup; if (virTestCompareToFile(actual, capsFile) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(capsFile); virObjectUnref(caps); virObjectUnref(orig); virObjectUnref(copy); VIR_FREE(actual); return ret; }
virCapsPtr lxctoolsCapabilitiesInit(void) { virCapsPtr caps; virCapsGuestPtr guest; if ((caps = virCapabilitiesNew(virArchFromHost(), true, true)) == NULL) goto no_memory; if (virCapabilitiesInitNUMA(caps) < 0) goto no_memory; if (virCapabilitiesAddHostMigrateTransport(caps, "tcp") < 0) goto no_memory; if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_EXE, caps->host.arch, NULL, NULL, 0, NULL)) == NULL) goto no_memory; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_LXCTOOLS, NULL, NULL, 0, NULL) == NULL) goto no_memory; return caps; no_memory: virObjectUnref(caps); return NULL; }
virCapsPtr libxlMakeCapabilities(libxl_ctx *ctx) { virCapsPtr caps; if ((caps = virCapabilitiesNew(virArchFromHost(), 1, 1)) == NULL) return NULL; if (libxlCapsInitHost(ctx, caps) < 0) goto error; if (libxlCapsInitNuma(ctx, caps) < 0) goto error; if (libxlCapsInitGuests(ctx, caps) < 0) goto error; return caps; error: virObjectUnref(caps); return NULL; }
static int fillAllCaps(virDomainCapsPtr domCaps) { virDomainCapsOSPtr os = &domCaps->os; virDomainCapsLoaderPtr loader = &os->loader; virDomainCapsCPUPtr cpu = &domCaps->cpu; virDomainCapsDeviceDiskPtr disk = &domCaps->disk; virDomainCapsDeviceGraphicsPtr graphics = &domCaps->graphics; virDomainCapsDeviceVideoPtr video = &domCaps->video; virDomainCapsDeviceHostdevPtr hostdev = &domCaps->hostdev; virCPUDef host = { .type = VIR_CPU_TYPE_HOST, .arch = VIR_ARCH_X86_64, .model = (char *) "host", .vendor = (char *) "CPU Vendorrr", }; domCaps->maxvcpus = 255; os->supported = true; loader->supported = true; SET_ALL_BITS(loader->type); SET_ALL_BITS(loader->readonly); if (fillStringValues(&loader->values, "/foo/bar", "/tmp/my_path", NULL) < 0) return -1; cpu->hostPassthrough = true; cpu->hostModel = virCPUDefCopy(&host); if (!(cpu->custom = virDomainCapsCPUModelsNew(3)) || virDomainCapsCPUModelsAdd(cpu->custom, "Model1", -1, VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0 || virDomainCapsCPUModelsAdd(cpu->custom, "Model2", -1, VIR_DOMCAPS_CPU_USABLE_NO) < 0 || virDomainCapsCPUModelsAdd(cpu->custom, "Model3", -1, VIR_DOMCAPS_CPU_USABLE_YES) < 0) return -1; disk->supported = true; SET_ALL_BITS(disk->diskDevice); SET_ALL_BITS(disk->bus); graphics->supported = true; SET_ALL_BITS(graphics->type); video->supported = true; SET_ALL_BITS(video->modelType); hostdev->supported = true; SET_ALL_BITS(hostdev->mode); SET_ALL_BITS(hostdev->startupPolicy); SET_ALL_BITS(hostdev->subsysType); SET_ALL_BITS(hostdev->capsType); SET_ALL_BITS(hostdev->pciBackend); return 0; } #if WITH_QEMU # include "testutilsqemu.h" static virCPUDef aarch64Cpu = { .sockets = 1, .cores = 1, .threads = 1, }; static virCPUDef ppc64leCpu = { .type = VIR_CPU_TYPE_HOST, .arch = VIR_ARCH_PPC64LE, .model = (char *) "POWER8", .sockets = 1, .cores = 1, .threads = 1, }; static virCPUDef x86Cpu = { .type = VIR_CPU_TYPE_HOST, .arch = VIR_ARCH_X86_64, .model = (char *) "Broadwell", .sockets = 1, .cores = 1, .threads = 1, }; static virCPUDef s390Cpu = { .type = VIR_CPU_TYPE_HOST, .arch = VIR_ARCH_S390X, .sockets = 1, .cores = 1, .threads = 1, }; static int fakeHostCPU(virCapsPtr caps, virArch arch) { virCPUDefPtr cpu; switch (arch) { case VIR_ARCH_AARCH64: cpu = &aarch64Cpu; break; case VIR_ARCH_PPC64LE: cpu = &ppc64leCpu; break; case VIR_ARCH_X86_64: cpu = &x86Cpu; break; case VIR_ARCH_S390X: cpu = &s390Cpu; break; default: virReportError(VIR_ERR_INTERNAL_ERROR, "cannot fake host CPU for arch %s", virArchToString(arch)); return -1; } if (!(caps->host.cpu = virCPUDefCopy(cpu))) return -1; return 0; } static int fillQemuCaps(virDomainCapsPtr domCaps, const char *name, const char *arch, const char *machine, virQEMUDriverConfigPtr cfg) { int ret = -1; char *path = NULL; virCapsPtr caps = NULL; virQEMUCapsPtr qemuCaps = NULL; virDomainCapsLoaderPtr loader = &domCaps->os.loader; if (!(caps = virCapabilitiesNew(domCaps->arch, false, false)) || fakeHostCPU(caps, domCaps->arch) < 0) goto cleanup; if (virAsprintf(&path, "%s/qemucapabilitiesdata/%s.%s.xml", abs_srcdir, name, arch) < 0 || !(qemuCaps = qemuTestParseCapabilities(caps, path))) goto cleanup; if (machine && VIR_STRDUP(domCaps->machine, virQEMUCapsGetCanonicalMachine(qemuCaps, machine)) < 0) goto cleanup; if (!domCaps->machine && VIR_STRDUP(domCaps->machine, virQEMUCapsGetDefaultMachine(qemuCaps)) < 0) goto cleanup; if (virQEMUCapsFillDomainCaps(caps, domCaps, qemuCaps, cfg->firmwares, cfg->nfirmwares) < 0) goto cleanup; /* The function above tries to query host's KVM & VFIO capabilities by * calling qemuHostdevHostSupportsPassthroughLegacy() and * qemuHostdevHostSupportsPassthroughVFIO() which, however, can't be * successfully mocked as they are not exposed as internal APIs. Therefore, * instead of mocking set the expected values here by hand. */ VIR_DOMAIN_CAPS_ENUM_SET(domCaps->hostdev.pciBackend, VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM, VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO); /* As of f05b6a918e28 we are expecting to see OVMF_CODE.fd file which * may not exists everywhere. */ while (loader->values.nvalues) VIR_FREE(loader->values.values[--loader->values.nvalues]); if (fillStringValues(&loader->values, "/usr/share/AAVMF/AAVMF_CODE.fd", "/usr/share/OVMF/OVMF_CODE.fd", NULL) < 0) goto cleanup; ret = 0; cleanup: virObjectUnref(caps); virObjectUnref(qemuCaps); VIR_FREE(path); return ret; } #endif /* WITH_QEMU */ #ifdef WITH_LIBXL # include "testutilsxen.h" static int fillXenCaps(virDomainCapsPtr domCaps) { virFirmwarePtr *firmwares; int ret = -1; if (VIR_ALLOC_N(firmwares, 2) < 0) return ret; if (VIR_ALLOC(firmwares[0]) < 0 || VIR_ALLOC(firmwares[1]) < 0) goto cleanup; if (VIR_STRDUP(firmwares[0]->name, "/usr/lib/xen/boot/hvmloader") < 0 || VIR_STRDUP(firmwares[1]->name, "/usr/lib/xen/boot/ovmf.bin") < 0) goto cleanup; if (libxlMakeDomainCapabilities(domCaps, firmwares, 2) < 0) goto cleanup; ret = 0; cleanup: virFirmwareFreeList(firmwares, 2); return ret; } #endif /* WITH_LIBXL */ #ifdef WITH_BHYVE # include "bhyve/bhyve_capabilities.h" static int fillBhyveCaps(virDomainCapsPtr domCaps, unsigned int *bhyve_caps) { virDomainCapsStringValuesPtr firmwares = NULL; int ret = -1; if (VIR_ALLOC(firmwares) < 0) return -1; if (fillStringValues(firmwares, "/foo/bar", "/foo/baz", NULL) < 0) goto cleanup; if (virBhyveDomainCapsFill(domCaps, *bhyve_caps, firmwares) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(firmwares); return ret; } #endif /* WITH_BHYVE */ enum testCapsType { CAPS_NONE, CAPS_ALL, CAPS_QEMU, CAPS_LIBXL, CAPS_BHYVE, }; struct testData { const char *name; const char *emulator; const char *machine; const char *arch; virDomainVirtType type; enum testCapsType capsType; const char *capsName; void *capsOpaque; }; static int test_virDomainCapsFormat(const void *opaque) { const struct testData *data = opaque; virDomainCapsPtr domCaps = NULL; char *path = NULL; char *domCapsXML = NULL; int ret = -1; if (virAsprintf(&path, "%s/domaincapsschemadata/%s.xml", abs_srcdir, data->name) < 0) goto cleanup; if (!(domCaps = virDomainCapsNew(data->emulator, data->machine, virArchFromString(data->arch), data->type))) goto cleanup; switch (data->capsType) { case CAPS_NONE: break; case CAPS_ALL: if (fillAllCaps(domCaps) < 0) goto cleanup; break; case CAPS_QEMU: #if WITH_QEMU if (fillQemuCaps(domCaps, data->capsName, data->arch, data->machine, data->capsOpaque) < 0) goto cleanup; #endif break; case CAPS_LIBXL: #if WITH_LIBXL if (fillXenCaps(domCaps) < 0) goto cleanup; #endif break; case CAPS_BHYVE: #if WITH_BHYVE if (fillBhyveCaps(domCaps, data->capsOpaque) < 0) goto cleanup; #endif break; } if (!(domCapsXML = virDomainCapsFormat(domCaps))) goto cleanup; if (virTestCompareToFile(domCapsXML, path) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(domCapsXML); VIR_FREE(path); virObjectUnref(domCaps); return ret; } static int mymain(void) { int ret = 0; #if WITH_BHYVE unsigned int bhyve_caps = 0; #endif #if WITH_QEMU virQEMUDriverConfigPtr cfg = virQEMUDriverConfigNew(false); if (!cfg) return EXIT_FAILURE; #endif #define DO_TEST(Name, Emulator, Machine, Arch, Type, CapsType) \ do { \ struct testData data = { \ .name = Name, \ .emulator = Emulator, \ .machine = Machine, \ .arch = Arch, \ .type = Type, \ .capsType = CapsType, \ }; \ if (virTestRun(Name, test_virDomainCapsFormat, &data) < 0) \ ret = -1; \ } while (0) #define DO_TEST_QEMU(Name, CapsName, Emulator, Machine, Arch, Type) \ do { \ char *name = NULL; \ if (virAsprintf(&name, "qemu_%s%s%s.%s", \ Name, \ Machine ? "-" : "", Machine ? Machine : "", \ Arch) < 0) { \ ret = -1; \ break; \ } \ struct testData data = { \ .name = name, \ .emulator = Emulator, \ .machine = Machine, \ .arch = Arch, \ .type = Type, \ .capsType = CAPS_QEMU, \ .capsName = CapsName, \ .capsOpaque = cfg, \ }; \ if (virTestRun(name, test_virDomainCapsFormat, &data) < 0) \ ret = -1; \ VIR_FREE(name); \ } while (0) #define DO_TEST_LIBXL(Name, Emulator, Machine, Arch, Type) \ do { \ struct testData data = { \ .name = Name, \ .emulator = Emulator, \ .machine = Machine, \ .arch = Arch, \ .type = Type, \ .capsType = CAPS_LIBXL, \ }; \ if (virTestRun(Name, test_virDomainCapsFormat, &data) < 0) \ ret = -1; \ } while (0) DO_TEST("basic", "/bin/emulatorbin", "my-machine-type", "x86_64", VIR_DOMAIN_VIRT_UML, CAPS_NONE); DO_TEST("full", "/bin/emulatorbin", "my-machine-type", "x86_64", VIR_DOMAIN_VIRT_KVM, CAPS_ALL); #define DO_TEST_BHYVE(Name, Emulator, BhyveCaps, Type) \ do { \ char *name = NULL; \ if (virAsprintf(&name, "bhyve_%s.x86_64", Name) < 0) { \ ret = -1; \ break; \ } \ struct testData data = { \ .name = name, \ .emulator = Emulator, \ .arch = "x86_64", \ .type = Type, \ .capsType = CAPS_BHYVE, \ .capsOpaque = BhyveCaps, \ }; \ if (virTestRun(name, test_virDomainCapsFormat, &data) < 0) \ ret = -1; \ VIR_FREE(name); \ } while (0) #if WITH_QEMU DO_TEST_QEMU("1.7.0", "caps_1.7.0", "/usr/bin/qemu-system-x86_64", NULL, "x86_64", VIR_DOMAIN_VIRT_KVM); DO_TEST_QEMU("2.6.0", "caps_2.6.0", "/usr/bin/qemu-system-x86_64", NULL, "x86_64", VIR_DOMAIN_VIRT_KVM); DO_TEST_QEMU("2.6.0", "caps_2.6.0-gicv2", "/usr/bin/qemu-system-aarch64", NULL, "aarch64", VIR_DOMAIN_VIRT_KVM); DO_TEST_QEMU("2.6.0-gicv2", "caps_2.6.0-gicv2", "/usr/bin/qemu-system-aarch64", "virt", "aarch64", VIR_DOMAIN_VIRT_KVM); DO_TEST_QEMU("2.6.0-gicv3", "caps_2.6.0-gicv3", "/usr/bin/qemu-system-aarch64", "virt", "aarch64", VIR_DOMAIN_VIRT_KVM); DO_TEST_QEMU("2.6.0", "caps_2.6.0", "/usr/bin/qemu-system-ppc64", NULL, "ppc64le", VIR_DOMAIN_VIRT_KVM); DO_TEST_QEMU("2.8.0", "caps_2.8.0", "/usr/bin/qemu-system-x86_64", NULL, "x86_64", VIR_DOMAIN_VIRT_KVM); DO_TEST_QEMU("2.8.0-tcg", "caps_2.8.0", "/usr/bin/qemu-system-x86_64", NULL, "x86_64", VIR_DOMAIN_VIRT_QEMU); DO_TEST_QEMU("2.9.0", "caps_2.9.0", "/usr/bin/qemu-system-x86_64", NULL, "x86_64", VIR_DOMAIN_VIRT_KVM); DO_TEST_QEMU("2.9.0", "caps_2.9.0", "/usr/bin/qemu-system-x86_64", "q35", "x86_64", VIR_DOMAIN_VIRT_KVM); DO_TEST_QEMU("2.9.0-tcg", "caps_2.9.0", "/usr/bin/qemu-system-x86_64", NULL, "x86_64", VIR_DOMAIN_VIRT_QEMU); DO_TEST_QEMU("2.7.0", "caps_2.7.0", "/usr/bin/qemu-system-s390x", NULL, "s390x", VIR_DOMAIN_VIRT_KVM); DO_TEST_QEMU("2.8.0", "caps_2.8.0", "/usr/bin/qemu-system-s390x", NULL, "s390x", VIR_DOMAIN_VIRT_KVM); virObjectUnref(cfg); #endif /* WITH_QEMU */ #if WITH_LIBXL # ifdef LIBXL_HAVE_PVUSB # define LIBXL_XENPV_CAPS "libxl-xenpv-usb" # define LIBXL_XENFV_CAPS "libxl-xenfv-usb" # else # define LIBXL_XENPV_CAPS "libxl-xenpv" # define LIBXL_XENFV_CAPS "libxl-xenfv" # endif DO_TEST_LIBXL(LIBXL_XENPV_CAPS, "/usr/bin/qemu-system-x86_64", "xenpv", "x86_64", VIR_DOMAIN_VIRT_XEN); DO_TEST_LIBXL(LIBXL_XENFV_CAPS, "/usr/bin/qemu-system-x86_64", "xenfv", "x86_64", VIR_DOMAIN_VIRT_XEN); #endif /* WITH_LIBXL */ #if WITH_BHYVE DO_TEST_BHYVE("basic", "/usr/sbin/bhyve", &bhyve_caps, VIR_DOMAIN_VIRT_BHYVE); bhyve_caps |= BHYVE_CAP_LPC_BOOTROM; DO_TEST_BHYVE("uefi", "/usr/sbin/bhyve", &bhyve_caps, VIR_DOMAIN_VIRT_BHYVE); bhyve_caps |= BHYVE_CAP_FBUF; DO_TEST_BHYVE("fbuf", "/usr/sbin/bhyve", &bhyve_caps, VIR_DOMAIN_VIRT_BHYVE); #endif /* WITH_BHYVE */ return ret; }
virCapsPtr testQemuCapsInit(void) { struct utsname utsname; virCapsPtr caps; virCapsGuestPtr guest; virCapsGuestMachinePtr *machines = NULL; int nmachines = 0; static const char *const xen_machines[] = { "xenner" }; static virCPUFeatureDef host_cpu_features[] = { { (char *) "lahf_lm", -1 }, { (char *) "xtpr", -1 }, { (char *) "cx16", -1 }, { (char *) "tm2", -1 }, { (char *) "est", -1 }, { (char *) "vmx", -1 }, { (char *) "ds_cpl", -1 }, { (char *) "pbe", -1 }, { (char *) "tm", -1 }, { (char *) "ht", -1 }, { (char *) "ss", -1 }, { (char *) "acpi", -1 }, { (char *) "ds", -1 } }; static virCPUDef host_cpu = { VIR_CPU_TYPE_HOST, /* type */ 0, /* match */ (char *) "x86_64", /* arch */ (char *) "core2duo", /* model */ (char *) "Intel", /* vendor */ 1, /* sockets */ 2, /* cores */ 1, /* threads */ ARRAY_CARDINALITY(host_cpu_features), /* nfeatures */ host_cpu_features /* features */ }; uname (&utsname); if ((caps = virCapabilitiesNew(utsname.machine, 0, 0)) == NULL) return NULL; if ((caps->host.cpu = virCPUDefCopy(&host_cpu)) == NULL || (machines = testQemuAllocMachines(&nmachines)) == NULL) goto cleanup; caps->ns.parse = qemuDomainDefNamespaceParse; caps->ns.free = qemuDomainDefNamespaceFree; caps->ns.format = qemuDomainDefNamespaceFormatXML; caps->ns.href = qemuDomainDefNamespaceHref; if ((guest = virCapabilitiesAddGuest(caps, "hvm", "i686", 32, "/usr/bin/qemu", NULL, nmachines, machines)) == NULL) goto cleanup; machines = NULL; if (virCapabilitiesAddGuestDomain(guest, "qemu", NULL, NULL, 0, NULL) == NULL) goto cleanup; if ((machines = testQemuAllocNewerMachines(&nmachines)) == NULL) goto cleanup; if ((guest = virCapabilitiesAddGuest(caps, "hvm", "x86_64", 64, "/usr/bin/qemu-system-x86_64", NULL, nmachines, machines)) == NULL) goto cleanup; machines = NULL; if (virCapabilitiesAddGuestDomain(guest, "qemu", NULL, NULL, 0, NULL) == NULL) goto cleanup; if ((machines = testQemuAllocMachines(&nmachines)) == NULL) goto cleanup; if (virCapabilitiesAddGuestDomain(guest, "kvm", "/usr/bin/kvm", NULL, nmachines, machines) == NULL) goto cleanup; machines = NULL; nmachines = ARRAY_CARDINALITY(xen_machines); if ((machines = virCapabilitiesAllocMachines(xen_machines, nmachines)) == NULL) goto cleanup; if ((guest = virCapabilitiesAddGuest(caps, "xen", "x86_64", 64, "/usr/bin/xenner", NULL, nmachines, machines)) == NULL) goto cleanup; machines = NULL; if (virCapabilitiesAddGuestDomain(guest, "kvm", "/usr/bin/kvm", NULL, 0, NULL) == NULL) goto cleanup; if (virTestGetDebug()) { char *caps_str; caps_str = virCapabilitiesFormatXML(caps); if (!caps_str) goto cleanup; fprintf(stderr, "QEMU driver capabilities:\n%s", caps_str); VIR_FREE(caps_str); } return caps; cleanup: virCapabilitiesFreeMachines(machines, nmachines); virCapabilitiesFree(caps); return NULL; }
/* Functions */ virCapsPtr virLXCDriverCapsInit(virLXCDriverPtr driver) { virCapsPtr caps; virCapsGuestPtr guest; virArch altArch; char *lxc_path = NULL; if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL) goto error; /* Some machines have problematic NUMA toplogy causing * unexpected failures. We don't want to break the lxc * driver in this scenario, so log errors & carry on */ if (nodeCapsInitNUMA(caps) < 0) { virCapabilitiesFreeNUMAInfo(caps); VIR_WARN("Failed to query host NUMA topology, disabling NUMA capabilities"); } /* Only probe for power management capabilities in the driver, * not in the emulator */ if (driver && virNodeSuspendGetTargetMask(&caps->host.powerMgmt) < 0) VIR_WARN("Failed to get host power management capabilities"); if (virGetHostUUID(caps->host.host_uuid)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot get the host uuid")); goto error; } if (!(lxc_path = virFileFindResource("libvirt_lxc", abs_topbuilddir "/src", LIBEXECDIR))) goto error; if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_EXE, caps->host.arch, lxc_path, NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_LXC, NULL, NULL, 0, NULL) == NULL) goto error; /* On 64-bit hosts, we can use personality() to request a 32bit process */ if ((altArch = lxcContainerGetAlt32bitArch(caps->host.arch)) != VIR_ARCH_NONE) { if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_EXE, altArch, lxc_path, NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_LXC, NULL, NULL, 0, NULL) == NULL) goto error; } VIR_FREE(lxc_path); if (driver) { /* Security driver data */ const char *doi, *model, *label, *type; doi = virSecurityManagerGetDOI(driver->securityManager); model = virSecurityManagerGetModel(driver->securityManager); label = virSecurityManagerGetBaseLabel(driver->securityManager, VIR_DOMAIN_VIRT_LXC); type = virDomainVirtTypeToString(VIR_DOMAIN_VIRT_LXC); /* Allocate the primary security driver for LXC. */ if (VIR_ALLOC(caps->host.secModels) < 0) goto error; caps->host.nsecModels = 1; if (VIR_STRDUP(caps->host.secModels[0].model, model) < 0) goto error; if (VIR_STRDUP(caps->host.secModels[0].doi, doi) < 0) goto error; if (label && virCapabilitiesHostSecModelAddBaseLabel(&caps->host.secModels[0], type, label) < 0) goto error; VIR_DEBUG("Initialized caps for security driver \"%s\" with " "DOI \"%s\"", model, doi); } else { VIR_INFO("No driver, not initializing security driver"); } return caps; error: VIR_FREE(lxc_path); virObjectUnref(caps); return NULL; }
virCapsPtr testQemuCapsInit(void) { virCapsPtr caps; virCapsGuestPtr guest; virCapsGuestMachinePtr *machines = NULL; int nmachines = 0; if (!(caps = virCapabilitiesNew(VIR_ARCH_X86_64, false, false))) return NULL; /* 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; if (!(cpuDefault = virCPUDefCopy(&cpuDefaultData)) || !(cpuHaswell = virCPUDefCopy(&cpuHaswellData))) goto cleanup; caps->host.cpu = cpuDefault; caps->host.nnumaCell_max = 4; if ((machines = testQemuAllocMachines(&nmachines)) == NULL) goto cleanup; if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_I686, "/usr/bin/qemu", NULL, nmachines, machines)) == NULL || !virCapabilitiesAddGuestFeature(guest, "cpuselection", true, false)) goto cleanup; machines = NULL; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU, NULL, NULL, 0, NULL) == NULL) goto cleanup; 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; if ((machines = testQemuAllocNewerMachines(&nmachines)) == NULL) goto cleanup; if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_X86_64, "/usr/bin/qemu-system-x86_64", NULL, nmachines, machines)) == NULL || !virCapabilitiesAddGuestFeature(guest, "cpuselection", true, false)) goto cleanup; machines = NULL; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU, NULL, NULL, 0, NULL) == NULL) goto cleanup; if ((machines = testQemuAllocMachines(&nmachines)) == NULL) goto cleanup; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_KVM, "/usr/bin/kvm", NULL, nmachines, machines) == NULL) goto cleanup; machines = NULL; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_KVM, "/usr/bin/kvm", NULL, 0, NULL) == NULL) goto cleanup; if (testQemuAddPPC64Guest(caps)) goto cleanup; if (testQemuAddPPC64LEGuest(caps)) goto cleanup; if (testQemuAddPPCGuest(caps)) goto cleanup; if (testQemuAddS390Guest(caps)) goto cleanup; if (testQemuAddArmGuest(caps)) goto cleanup; if (testQemuAddAARCH64Guest(caps)) goto cleanup; if (virTestGetDebug()) { char *caps_str; caps_str = virCapabilitiesFormatXML(caps); if (!caps_str) goto cleanup; VIR_TEST_DEBUG("QEMU driver capabilities:\n%s", caps_str); VIR_FREE(caps_str); } return caps; cleanup: virCapabilitiesFreeMachines(machines, nmachines); if (caps->host.cpu != cpuDefault) virCPUDefFree(cpuDefault); if (caps->host.cpu != cpuHaswell) virCPUDefFree(cpuHaswell); virObjectUnref(caps); return NULL; }
static virCapsPtr parallelsBuildCapabilities(void) { virCapsPtr caps = NULL; virCPUDefPtr cpu = NULL; virCPUDataPtr data = NULL; virCapsGuestPtr guest; virNodeInfo nodeinfo; if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL) return NULL; if (nodeCapsInitNUMA(caps) < 0) goto error; if ((guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_X86_64, "parallels", NULL, 0, NULL)) == NULL) goto error; if ((guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_I686, "parallels", NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, "parallels", NULL, NULL, 0, NULL) == NULL) goto error; if ((guest = virCapabilitiesAddGuest(caps, "exe", VIR_ARCH_X86_64, "parallels", NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, "parallels", NULL, NULL, 0, NULL) == NULL) goto error; if (nodeGetInfo(&nodeinfo)) goto error; if (VIR_ALLOC(cpu) < 0) goto error; cpu->arch = caps->host.arch; cpu->type = VIR_CPU_TYPE_HOST; cpu->sockets = nodeinfo.sockets; cpu->cores = nodeinfo.cores; cpu->threads = nodeinfo.threads; caps->host.cpu = cpu; if (!(data = cpuNodeData(cpu->arch)) || cpuDecode(cpu, data, NULL, 0, NULL) < 0) { goto cleanup; } cleanup: cpuDataFree(data); return caps; error: virObjectUnref(caps); goto cleanup; }
virCapsPtr vmwareCapsInit(void) { virCapsPtr caps = NULL; virCapsGuestPtr guest = NULL; virCPUDefPtr cpu = NULL; virCPUDataPtr data = NULL; if ((caps = virCapabilitiesNew(virArchFromHost(), 0, 0)) == NULL) goto error; if (nodeCapsInitNUMA(caps) < 0) goto error; /* i686 guests are always supported */ if ((guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_I686, NULL, NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, "vmware", NULL, NULL, 0, NULL) == NULL) goto error; if (VIR_ALLOC(cpu) < 0) goto error; cpu->arch = caps->host.arch; cpu->type = VIR_CPU_TYPE_HOST; if (!(data = cpuNodeData(cpu->arch)) || cpuDecode(cpu, data, NULL, 0, NULL) < 0) { goto error; } /* x86_64 guests are supported if * - Host arch is x86_64 * Or * - Host CPU is x86_64 with virtualization extensions */ if (caps->host.arch == VIR_ARCH_X86_64 || (cpuHasFeature(data, "lm") && (cpuHasFeature(data, "vmx") || cpuHasFeature(data, "svm")))) { if ((guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_X86_64, NULL, NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, "vmware", NULL, NULL, 0, NULL) == NULL) goto error; } cleanup: virCPUDefFree(cpu); cpuDataFree(data); return caps; error: virObjectUnref(caps); goto cleanup; }
/* Functions */ virCapsPtr lxcCapsInit(virLXCDriverPtr driver) { virCapsPtr caps; virCapsGuestPtr guest; virArch altArch; if ((caps = virCapabilitiesNew(virArchFromHost(), 0, 0)) == NULL) goto error; /* Some machines have problematic NUMA toplogy causing * unexpected failures. We don't want to break the QEMU * driver in this scenario, so log errors & carry on */ if (nodeCapsInitNUMA(caps) < 0) { virCapabilitiesFreeNUMAInfo(caps); VIR_WARN("Failed to query host NUMA topology, disabling NUMA capabilities"); } if (virNodeSuspendGetTargetMask(&caps->host.powerMgmt) < 0) VIR_WARN("Failed to get host power management capabilities"); if (virGetHostUUID(caps->host.host_uuid)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot get the host uuid")); goto error; } if ((guest = virCapabilitiesAddGuest(caps, "exe", caps->host.arch, LIBEXECDIR "/libvirt_lxc", NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, "lxc", NULL, NULL, 0, NULL) == NULL) goto error; /* On 64-bit hosts, we can use personality() to request a 32bit process */ if ((altArch = lxcContainerGetAlt32bitArch(caps->host.arch)) != VIR_ARCH_NONE) { if ((guest = virCapabilitiesAddGuest(caps, "exe", altArch, LIBEXECDIR "/libvirt_lxc", NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, "lxc", NULL, NULL, 0, NULL) == NULL) goto error; } if (driver) { /* Security driver data */ const char *doi, *model; doi = virSecurityManagerGetDOI(driver->securityManager); model = virSecurityManagerGetModel(driver->securityManager); if (STRNEQ(model, "none")) { /* Allocate just the primary security driver for LXC. */ if (VIR_ALLOC(caps->host.secModels) < 0) goto no_memory; caps->host.nsecModels = 1; if (VIR_STRDUP(caps->host.secModels[0].model, model) < 0) goto error; if (VIR_STRDUP(caps->host.secModels[0].doi, doi) < 0) goto error; } VIR_DEBUG("Initialized caps for security driver \"%s\" with " "DOI \"%s\"", model, doi); } else { VIR_INFO("No driver, not initializing security driver"); } return caps; no_memory: virReportOOMError(); error: virObjectUnref(caps); return NULL; }
virCapsPtr testQemuCapsInit(void) { virCapsPtr caps; virCapsGuestPtr guest; virCapsGuestMachinePtr *machines = NULL; int nmachines = 0; static const char *const xen_machines[] = { "xenner" }; static virCPUFeatureDef host_cpu_features[] = { { (char *) "lahf_lm", -1 }, { (char *) "xtpr", -1 }, { (char *) "cx16", -1 }, { (char *) "tm2", -1 }, { (char *) "est", -1 }, { (char *) "vmx", -1 }, { (char *) "ds_cpl", -1 }, { (char *) "pbe", -1 }, { (char *) "tm", -1 }, { (char *) "ht", -1 }, { (char *) "ss", -1 }, { (char *) "acpi", -1 }, { (char *) "ds", -1 } }; static virCPUDef host_cpu = { 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(host_cpu_features), /* nfeatures */ ARRAY_CARDINALITY(host_cpu_features), /* nfeatures_max */ host_cpu_features, /* features */ 0, /* ncells */ 0, /* ncells_max */ NULL, /* cells */ 0, /* cells_cpus */ }; if ((caps = virCapabilitiesNew(host_cpu.arch, 0, 0)) == NULL) return NULL; if ((caps->host.cpu = virCPUDefCopy(&host_cpu)) == NULL || (machines = testQemuAllocMachines(&nmachines)) == NULL) goto cleanup; if ((guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_I686, "/usr/bin/qemu", NULL, nmachines, machines)) == NULL || !virCapabilitiesAddGuestFeature(guest, "cpuselection", 1, 0)) goto cleanup; machines = NULL; if (virCapabilitiesAddGuestDomain(guest, "qemu", NULL, NULL, 0, NULL) == NULL) goto cleanup; if ((machines = testQemuAllocNewerMachines(&nmachines)) == NULL) goto cleanup; if ((guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_X86_64, "/usr/bin/qemu-system-x86_64", NULL, nmachines, machines)) == NULL || !virCapabilitiesAddGuestFeature(guest, "cpuselection", 1, 0)) goto cleanup; machines = NULL; if (virCapabilitiesAddGuestDomain(guest, "qemu", NULL, NULL, 0, NULL) == NULL) goto cleanup; if ((machines = testQemuAllocMachines(&nmachines)) == NULL) goto cleanup; if (virCapabilitiesAddGuestDomain(guest, "kvm", "/usr/bin/kvm", NULL, nmachines, machines) == NULL) goto cleanup; machines = NULL; nmachines = ARRAY_CARDINALITY(xen_machines); if ((machines = virCapabilitiesAllocMachines(xen_machines, nmachines)) == NULL) goto cleanup; if ((guest = virCapabilitiesAddGuest(caps, "xen", VIR_ARCH_X86_64, "/usr/bin/xenner", NULL, nmachines, machines)) == NULL) goto cleanup; machines = NULL; if (virCapabilitiesAddGuestDomain(guest, "kvm", "/usr/bin/kvm", NULL, 0, NULL) == NULL) goto cleanup; if (testQemuAddPPC64Guest(caps)) goto cleanup; if (testQemuAddPPCGuest(caps)) goto cleanup; if (testQemuAddS390Guest(caps)) goto cleanup; if (virTestGetDebug()) { char *caps_str; caps_str = virCapabilitiesFormatXML(caps); if (!caps_str) goto cleanup; fprintf(stderr, "QEMU driver capabilities:\n%s", caps_str); VIR_FREE(caps_str); } return caps; cleanup: virCapabilitiesFreeMachines(machines, nmachines); virObjectUnref(caps); return NULL; }
static virCapsPtr buildVirCapabilities(int max_cells, int max_cpus_in_cell, int max_mem_in_cell) { virCapsPtr caps; virCapsHostNUMACellCPUPtr cell_cpus = NULL; virCapsHostNUMACellSiblingInfoPtr siblings = NULL; int core_id, cell_id, nsiblings; int id; size_t i; if ((caps = virCapabilitiesNew(VIR_ARCH_X86_64, 0, 0)) == NULL) goto error; id = 0; for (cell_id = 0; cell_id < max_cells; cell_id++) { if (VIR_ALLOC_N(cell_cpus, max_cpus_in_cell) < 0) goto error; for (core_id = 0; core_id < max_cpus_in_cell; core_id++) { cell_cpus[core_id].id = id; cell_cpus[core_id].socket_id = cell_id; cell_cpus[core_id].core_id = id + core_id; if (!(cell_cpus[core_id].siblings = virBitmapNew(max_cpus_in_cell))) goto error; ignore_value(virBitmapSetBit(cell_cpus[core_id].siblings, id)); } id++; if (VIR_ALLOC_N(siblings, max_cells) < 0) goto error; nsiblings = max_cells; for (i = 0; i < nsiblings; i++) { siblings[i].node = i; /* Some magical constants, see virNumaGetDistances() * for their description. */ siblings[i].distance = cell_id == i ? 10 : 20; } if (virCapabilitiesAddHostNUMACell(caps, cell_id, max_mem_in_cell, max_cpus_in_cell, cell_cpus, nsiblings, siblings, 0, NULL) < 0) goto error; cell_cpus = NULL; siblings = NULL; } return caps; error: virCapabilitiesClearHostNUMACellCPUTopology(cell_cpus, max_cpus_in_cell); VIR_FREE(cell_cpus); VIR_FREE(siblings); virObjectUnref(caps); return NULL; }
static int fillQemuCaps(virDomainCapsPtr domCaps, const char *name, const char *arch, const char *machine, virQEMUDriverConfigPtr cfg) { int ret = -1; char *path = NULL; virCapsPtr caps = NULL; virQEMUCapsPtr qemuCaps = NULL; virDomainCapsLoaderPtr loader = &domCaps->os.loader; if (!(caps = virCapabilitiesNew(domCaps->arch, false, false)) || fakeHostCPU(caps, domCaps->arch) < 0) goto cleanup; if (virAsprintf(&path, "%s/qemucapabilitiesdata/%s.%s.xml", abs_srcdir, name, arch) < 0 || !(qemuCaps = qemuTestParseCapabilities(caps, path))) goto cleanup; if (machine && VIR_STRDUP(domCaps->machine, virQEMUCapsGetCanonicalMachine(qemuCaps, machine)) < 0) goto cleanup; if (!domCaps->machine && VIR_STRDUP(domCaps->machine, virQEMUCapsGetDefaultMachine(qemuCaps)) < 0) goto cleanup; if (virQEMUCapsFillDomainCaps(caps, domCaps, qemuCaps, cfg->firmwares, cfg->nfirmwares) < 0) goto cleanup; /* The function above tries to query host's KVM & VFIO capabilities by * calling qemuHostdevHostSupportsPassthroughLegacy() and * qemuHostdevHostSupportsPassthroughVFIO() which, however, can't be * successfully mocked as they are not exposed as internal APIs. Therefore, * instead of mocking set the expected values here by hand. */ VIR_DOMAIN_CAPS_ENUM_SET(domCaps->hostdev.pciBackend, VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM, VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO); /* As of f05b6a918e28 we are expecting to see OVMF_CODE.fd file which * may not exists everywhere. */ while (loader->values.nvalues) VIR_FREE(loader->values.values[--loader->values.nvalues]); if (fillStringValues(&loader->values, "/usr/share/AAVMF/AAVMF_CODE.fd", "/usr/share/OVMF/OVMF_CODE.fd", NULL) < 0) goto cleanup; ret = 0; cleanup: virObjectUnref(caps); virObjectUnref(qemuCaps); VIR_FREE(path); return ret; }
virCapsPtr testQemuCapsInit(void) { virCapsPtr caps; if (!(caps = virCapabilitiesNew(VIR_ARCH_X86_64, false, false))) return NULL; /* 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; if (!(cpuDefault = virCPUDefCopy(&cpuDefaultData)) || !(cpuHaswell = virCPUDefCopy(&cpuHaswellData)) || !(cpuPower8 = virCPUDefCopy(&cpuPower8Data)) || !(cpuPower9 = virCPUDefCopy(&cpuPower9Data))) goto cleanup; qemuTestSetHostCPU(caps, NULL); caps->host.nnumaCell_max = 4; if (testQemuAddI686Guest(caps) < 0) goto cleanup; if (testQemuAddX86_64Guest(caps) < 0) goto cleanup; if (testQemuAddPPC64Guest(caps)) goto cleanup; if (testQemuAddPPC64LEGuest(caps)) goto cleanup; if (testQemuAddPPCGuest(caps)) goto cleanup; if (testQemuAddS390Guest(caps)) goto cleanup; if (testQemuAddArmGuest(caps)) goto cleanup; if (testQemuAddAARCH64Guest(caps)) goto cleanup; if (virTestGetDebug()) { char *caps_str; caps_str = virCapabilitiesFormatXML(caps); if (!caps_str) goto cleanup; VIR_TEST_DEBUG("QEMU driver capabilities:\n%s", caps_str); VIR_FREE(caps_str); } return caps; cleanup: caps->host.cpu = NULL; virCPUDefFree(cpuDefault); virCPUDefFree(cpuHaswell); virCPUDefFree(cpuPower8); virObjectUnref(caps); return NULL; }