static int testQemuAddS390Guest(virCapsPtr caps) { static const char *s390_machines[] = { "s390-virtio", "s390-ccw-virtio" }; virCapsGuestMachinePtr *machines = NULL; virCapsGuestPtr guest; machines = virCapabilitiesAllocMachines(s390_machines, ARRAY_CARDINALITY(s390_machines)); if (!machines) goto error; guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_S390X, "/usr/bin/qemu-system-s390x", NULL, ARRAY_CARDINALITY(s390_machines), machines); if (!guest) goto error; if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU, NULL, NULL, 0, NULL)) goto error; return 0; error: virCapabilitiesFreeMachines(machines, ARRAY_CARDINALITY(s390_machines)); return -1; }
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; guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_AARCH64, "/usr/bin/qemu-system-aarch64", NULL, ARRAY_CARDINALITY(machines), capsmachines); if (!guest) goto error; if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU, NULL, NULL, 0, NULL)) goto error; return 0; error: virCapabilitiesFreeMachines(capsmachines, ARRAY_CARDINALITY(machines)); return -1; }
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; guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_ARMV7L, "/usr/bin/qemu-system-arm", NULL, ARRAY_CARDINALITY(machines), capsmachines); if (!guest) goto error; if (!virCapabilitiesAddGuestDomain(guest, "qemu", NULL, NULL, 0, NULL)) goto error; return 0; error: virCapabilitiesFreeMachines(capsmachines, ARRAY_CARDINALITY(machines)); return -1; }
static int testQemuAddPPCGuest(virCapsPtr caps) { static const char *machine[] = { "g3beige", "mac99", "prep", "ppce500" }; virCapsGuestMachinePtr *machines = NULL; virCapsGuestPtr guest; machines = virCapabilitiesAllocMachines(machine, 1); if (!machines) goto error; guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_PPC, "/usr/bin/qemu-system-ppc", NULL, 1, machines); if (!guest) goto error; if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU, NULL, NULL, 0, NULL)) goto error; return 0; error: /* No way to free a guest? */ virCapabilitiesFreeMachines(machines, 1); return -1; }
static int testQemuAddPPC64Guest(virCapsPtr caps) { static const char *machine[] = { "pseries" }; virCapsGuestMachinePtr *machines = NULL; virCapsGuestPtr guest; machines = virCapabilitiesAllocMachines(machine, 1); if (!machines) goto error; guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_PPC64, "/usr/bin/qemu-system-ppc64", NULL, 1, machines); if (!guest) goto error; if (!virCapabilitiesAddGuestDomain(guest, "qemu", NULL, NULL, 0, NULL)) goto error; return 0; error: /* No way to free a guest? */ virCapabilitiesFreeMachines(machines, 1); return -1; }
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; guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_ARMV7L, QEMUBinList[TEST_UTILS_QEMU_BIN_ARM], NULL, ARRAY_CARDINALITY(machines), capsmachines); if (!guest) goto error; if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU, NULL, NULL, 0, NULL)) goto error; return 0; error: virCapabilitiesFreeMachines(capsmachines, ARRAY_CARDINALITY(machines)); return -1; }
static int testQemuAddPPC64LEGuest(virCapsPtr caps) { static const char *machine[] = { "pseries" }; virCapsGuestMachinePtr *machines = NULL; virCapsGuestPtr guest; machines = virCapabilitiesAllocMachines(machine, 1); if (!machines) goto error; guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_PPC64LE, QEMUBinList[TEST_UTILS_QEMU_BIN_PPC64], NULL, 1, machines); if (!guest) goto error; if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU, NULL, NULL, 0, NULL)) goto error; return 0; error: /* No way to free a guest? */ virCapabilitiesFreeMachines(machines, 1); return -1; }
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; }
/* 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" }; if (VIR_STRDUP(canonical, x86_machines[0]) < 0) 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; }
static int libxlCapsInitGuests(libxl_ctx *ctx, virCapsPtr caps) { const libxl_version_info *ver_info; int err; regex_t regex; char *str, *token; regmatch_t subs[4]; char *saveptr = NULL; size_t i; virArch hostarch = caps->host.arch; struct guest_arch guest_archs[32]; int nr_guest_archs = 0; memset(guest_archs, 0, sizeof(guest_archs)); if ((ver_info = libxl_get_version_info(ctx)) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to get version info from libxenlight")); return -1; } err = regcomp(®ex, XEN_CAP_REGEX, REG_EXTENDED); if (err != 0) { char error[100]; regerror(err, ®ex, error, sizeof(error)); virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to compile regex %s"), error); return -1; } /* Format of capabilities string is documented in the code in * xen-unstable.hg/xen/arch/.../setup.c. * * It is a space-separated list of supported guest architectures. * * For x86: * TYP-VER-ARCH[p] * ^ ^ ^ ^ * | | | +-- PAE supported * | | +------- x86_32 or x86_64 * | +----------- the version of Xen, eg. "3.0" * +--------------- "xen" or "hvm" for para or full virt respectively * * For IA64: * TYP-VER-ARCH[be] * ^ ^ ^ ^ * | | | +-- Big-endian supported * | | +------- always "ia64" * | +----------- the version of Xen, eg. "3.0" * +--------------- "xen" or "hvm" for para or full virt respectively */ /* Split capabilities string into tokens. strtok_r is OK here because * we "own" the buffer. Parse out the features from each token. */ for (str = ver_info->capabilities, nr_guest_archs = 0; nr_guest_archs < sizeof(guest_archs) / sizeof(guest_archs[0]) && (token = strtok_r(str, " ", &saveptr)) != NULL; str = NULL) { if (regexec(®ex, token, sizeof(subs) / sizeof(subs[0]), subs, 0) == 0) { int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm"); virArch arch; int pae = 0, nonpae = 0, ia64_be = 0; if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) { arch = VIR_ARCH_I686; if (subs[3].rm_so != -1 && STRPREFIX(&token[subs[3].rm_so], "p")) pae = 1; else nonpae = 1; } else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) { arch = VIR_ARCH_X86_64; } else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) { arch = VIR_ARCH_ITANIUM; if (subs[3].rm_so != -1 && STRPREFIX(&token[subs[3].rm_so], "be")) ia64_be = 1; } else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) { arch = VIR_ARCH_PPC64; } else if (STRPREFIX(&token[subs[2].rm_so], "armv7l")) { arch = VIR_ARCH_ARMV7L; } else if (STRPREFIX(&token[subs[2].rm_so], "aarch64")) { arch = VIR_ARCH_AARCH64; } else { continue; } /* Search for existing matching (model,hvm) tuple */ for (i = 0; i < nr_guest_archs; i++) { if ((guest_archs[i].arch == arch) && guest_archs[i].hvm == hvm) break; } /* Too many arch flavours - highly unlikely ! */ if (i >= ARRAY_CARDINALITY(guest_archs)) continue; /* Didn't find a match, so create a new one */ if (i == nr_guest_archs) nr_guest_archs++; guest_archs[i].arch = arch; guest_archs[i].hvm = hvm; /* Careful not to overwrite a previous positive setting with a negative one here - some archs can do both pae & non-pae, but Xen reports separately capabilities so we're merging archs */ if (pae) guest_archs[i].pae = pae; if (nonpae) guest_archs[i].nonpae = nonpae; if (ia64_be) guest_archs[i].ia64_be = ia64_be; } } regfree(®ex); for (i = 0; i < nr_guest_archs; ++i) { virCapsGuestPtr guest; char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"}; virCapsGuestMachinePtr *machines; if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL) return -1; if ((guest = virCapabilitiesAddGuest(caps, guest_archs[i].hvm ? "hvm" : "xen", guest_archs[i].arch, "qemu-dm", (guest_archs[i].hvm ? "hvmloader" : NULL), 1, machines)) == NULL) { virCapabilitiesFreeMachines(machines, 1); return -1; } machines = NULL; if (virCapabilitiesAddGuestDomain(guest, "xen", NULL, NULL, 0, NULL) == NULL) return -1; if (guest_archs[i].pae && virCapabilitiesAddGuestFeature(guest, "pae", 1, 0) == NULL) return -1; if (guest_archs[i].nonpae && virCapabilitiesAddGuestFeature(guest, "nonpae", 1, 0) == NULL) return -1; if (guest_archs[i].ia64_be && virCapabilitiesAddGuestFeature(guest, "ia64_be", 1, 0) == NULL) return -1; if (guest_archs[i].hvm) { if (virCapabilitiesAddGuestFeature(guest, "acpi", 1, 1) == NULL) return -1; if (virCapabilitiesAddGuestFeature(guest, "apic", 1, 0) == NULL) return -1; if (virCapabilitiesAddGuestFeature(guest, "hap", 0, 1) == NULL) return -1; } } return 0; }
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; }
virCapsPtr testQemuCapsInit(void) { virCapsPtr caps; virCapsGuestPtr guest; virCapsGuestMachinePtr *machines = NULL; int nmachines = 0; static const char *const xen_machines[] = { "xenner" }; 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; nmachines = ARRAY_CARDINALITY(xen_machines); if ((machines = virCapabilitiesAllocMachines(xen_machines, nmachines)) == NULL) goto cleanup; if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_XEN, VIR_ARCH_X86_64, "/usr/bin/xenner", 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; }
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; }