mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
Implement CPU selection in QEMU driver
* src/qemu/qemu_conf.c src/qemu/qemu_conf.h src/qemu/qemu_driver.c: add the new entry point, extend capabilities and code to interract with qemu
This commit is contained in:
parent
d5ef0a69e9
commit
ffb13b1115
@ -52,6 +52,7 @@
|
|||||||
#include "nodeinfo.h"
|
#include "nodeinfo.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
|
#include "cpu/cpu.h"
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_QEMU
|
#define VIR_FROM_THIS VIR_FROM_QEMU
|
||||||
|
|
||||||
@ -608,6 +609,151 @@ qemudGetOldMachines(const char *ostype,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef int
|
||||||
|
(*qemudParseCPUModels)(const char *output,
|
||||||
|
unsigned int *retcount,
|
||||||
|
const char ***retcpus);
|
||||||
|
|
||||||
|
/* Format:
|
||||||
|
* <arch> <model>
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
qemudParseX86Models(const char *output,
|
||||||
|
unsigned int *retcount,
|
||||||
|
const char ***retcpus)
|
||||||
|
{
|
||||||
|
const char *p = output;
|
||||||
|
const char *next;
|
||||||
|
unsigned int count = 0;
|
||||||
|
const char **cpus = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
do {
|
||||||
|
const char *t;
|
||||||
|
|
||||||
|
if ((next = strchr(p, '\n')))
|
||||||
|
next++;
|
||||||
|
|
||||||
|
if (!(t = strchr(p, ' ')) || (next && t >= next))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!STRPREFIX(p, "x86"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
p = t;
|
||||||
|
while (*p == ' ')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
if (*p == '\0' || *p == '\n')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (retcpus) {
|
||||||
|
if (VIR_REALLOC_N(cpus, count + 1) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (next)
|
||||||
|
cpus[count] = strndup(p, next - p - 1);
|
||||||
|
else
|
||||||
|
cpus[count] = strdup(p);
|
||||||
|
|
||||||
|
if (!cpus[count])
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
} while ((p = next));
|
||||||
|
|
||||||
|
if (retcount)
|
||||||
|
*retcount = count;
|
||||||
|
if (retcpus)
|
||||||
|
*retcpus = cpus;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (cpus) {
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
VIR_FREE(cpus[i]);
|
||||||
|
}
|
||||||
|
VIR_FREE(cpus);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
qemudProbeCPUModels(const char *qemu,
|
||||||
|
const char *arch,
|
||||||
|
unsigned int *count,
|
||||||
|
const char ***cpus)
|
||||||
|
{
|
||||||
|
const char *const qemuarg[] = { qemu, "-cpu", "?", NULL };
|
||||||
|
const char *const qemuenv[] = { "LC_ALL=C", NULL };
|
||||||
|
enum { MAX_MACHINES_OUTPUT_SIZE = 1024*4 };
|
||||||
|
char *output = NULL;
|
||||||
|
int newstdout = -1;
|
||||||
|
int ret = -1;
|
||||||
|
pid_t child;
|
||||||
|
int status;
|
||||||
|
int len;
|
||||||
|
qemudParseCPUModels parse;
|
||||||
|
|
||||||
|
if (count)
|
||||||
|
*count = 0;
|
||||||
|
if (cpus)
|
||||||
|
*cpus = NULL;
|
||||||
|
|
||||||
|
if (STREQ(arch, "i686") || STREQ(arch, "x86_64"))
|
||||||
|
parse = qemudParseX86Models;
|
||||||
|
else {
|
||||||
|
VIR_DEBUG(_("don't know how to parse %s CPU models"), arch);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virExec(NULL, qemuarg, qemuenv, NULL,
|
||||||
|
&child, -1, &newstdout, NULL, VIR_EXEC_CLEAR_CAPS) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
len = virFileReadLimFD(newstdout, MAX_MACHINES_OUTPUT_SIZE, &output);
|
||||||
|
if (len < 0) {
|
||||||
|
virReportSystemError(NULL, errno, "%s",
|
||||||
|
_("Unable to read QEMU supported CPU models"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parse(output, count, cpus) < 0) {
|
||||||
|
virReportOOMError(NULL);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(output);
|
||||||
|
if (close(newstdout) < 0)
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
|
rewait:
|
||||||
|
if (waitpid(child, &status, 0) != child) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
goto rewait;
|
||||||
|
|
||||||
|
VIR_ERROR(_("Unexpected exit status from qemu %d pid %lu"),
|
||||||
|
WEXITSTATUS(status), (unsigned long)child);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
/* Check & log unexpected exit status, but don't fail,
|
||||||
|
* as there's really no need to throw an error if we did
|
||||||
|
* actually read a valid version number above */
|
||||||
|
if (WEXITSTATUS(status) != 0) {
|
||||||
|
VIR_WARN(_("Unexpected exit status '%d', qemu probably failed"),
|
||||||
|
WEXITSTATUS(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qemudCapsInitGuest(virCapsPtr caps,
|
qemudCapsInitGuest(virCapsPtr caps,
|
||||||
virCapsPtr old_caps,
|
virCapsPtr old_caps,
|
||||||
@ -624,6 +770,7 @@ qemudCapsInitGuest(virCapsPtr caps,
|
|||||||
virCapsGuestMachinePtr *machines = NULL;
|
virCapsGuestMachinePtr *machines = NULL;
|
||||||
int nmachines = 0;
|
int nmachines = 0;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
unsigned int ncpus;
|
||||||
|
|
||||||
/* Check for existance of base emulator, or alternate base
|
/* Check for existance of base emulator, or alternate base
|
||||||
* which can be used with magic cpu choice
|
* which can be used with magic cpu choice
|
||||||
@ -725,6 +872,11 @@ qemudCapsInitGuest(virCapsPtr caps,
|
|||||||
|
|
||||||
guest->arch.defaultInfo.emulator_mtime = binary_mtime;
|
guest->arch.defaultInfo.emulator_mtime = binary_mtime;
|
||||||
|
|
||||||
|
if (qemudProbeCPUModels(binary, info->arch, &ncpus, NULL) == 0
|
||||||
|
&& ncpus > 0
|
||||||
|
&& !virCapabilitiesAddGuestFeature(guest, "cpuselection", 1, 0))
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (hvm) {
|
if (hvm) {
|
||||||
if (virCapabilitiesAddGuestDomain(guest,
|
if (virCapabilitiesAddGuestDomain(guest,
|
||||||
"qemu",
|
"qemu",
|
||||||
@ -808,6 +960,49 @@ qemudCapsInitGuest(virCapsPtr caps,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemudCapsInitCPU(virCapsPtr caps,
|
||||||
|
const char *arch)
|
||||||
|
{
|
||||||
|
virCPUDefPtr cpu = NULL;
|
||||||
|
union cpuData *data = NULL;
|
||||||
|
virNodeInfo nodeinfo;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(cpu) < 0
|
||||||
|
|| !(cpu->arch = strdup(arch))) {
|
||||||
|
virReportOOMError(NULL);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodeGetInfo(NULL, &nodeinfo))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
cpu->type = VIR_CPU_TYPE_HOST;
|
||||||
|
cpu->sockets = nodeinfo.sockets;
|
||||||
|
cpu->cores = nodeinfo.cores;
|
||||||
|
cpu->threads = nodeinfo.threads;
|
||||||
|
|
||||||
|
if (!(data = cpuNodeData(NULL, arch))
|
||||||
|
|| cpuDecode(NULL, cpu, data, 0, NULL) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
caps->host.cpu = cpu;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
cpuDataFree(NULL, arch, data);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
error:
|
||||||
|
virCPUDefFree(cpu);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
virCapsPtr qemudCapsInit(virCapsPtr old_caps) {
|
virCapsPtr qemudCapsInit(virCapsPtr old_caps) {
|
||||||
struct utsname utsname;
|
struct utsname utsname;
|
||||||
virCapsPtr caps;
|
virCapsPtr caps;
|
||||||
@ -832,6 +1027,15 @@ virCapsPtr qemudCapsInit(virCapsPtr old_caps) {
|
|||||||
VIR_WARN0("Failed to query host NUMA topology, disabling NUMA capabilities");
|
VIR_WARN0("Failed to query host NUMA topology, disabling NUMA capabilities");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (old_caps == NULL || old_caps->host.cpu == NULL) {
|
||||||
|
if (qemudCapsInitCPU(caps, utsname.machine) < 0)
|
||||||
|
VIR_WARN0("Failed to get host CPU");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
caps->host.cpu = old_caps->host.cpu;
|
||||||
|
old_caps->host.cpu = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
virCapabilitiesAddHostMigrateTransport(caps,
|
virCapabilitiesAddHostMigrateTransport(caps,
|
||||||
"tcp");
|
"tcp");
|
||||||
|
|
||||||
@ -1563,6 +1767,98 @@ static void qemudBuildCommandLineChrDevStr(virDomainChrDefPtr dev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemudBuildCommandLineCPU(virConnectPtr conn,
|
||||||
|
const struct qemud_driver *driver,
|
||||||
|
const virDomainDefPtr def,
|
||||||
|
const char *emulator,
|
||||||
|
const struct utsname *ut,
|
||||||
|
char **opt)
|
||||||
|
{
|
||||||
|
const virCPUDefPtr host = driver->caps->host.cpu;
|
||||||
|
virCPUDefPtr guest = NULL;
|
||||||
|
unsigned int ncpus;
|
||||||
|
const char **cpus = NULL;
|
||||||
|
union cpuData *data = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (qemudProbeCPUModels(emulator, ut->machine, &ncpus, &cpus) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (ncpus > 0 && host && def->cpu && def->cpu->model) {
|
||||||
|
virCPUCompareResult cmp;
|
||||||
|
|
||||||
|
cmp = cpuGuestData(conn, host, def->cpu, &data);
|
||||||
|
switch (cmp) {
|
||||||
|
case VIR_CPU_COMPARE_INCOMPATIBLE:
|
||||||
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("guest CPU is not compatible with host CPU"));
|
||||||
|
/* fall through */
|
||||||
|
case VIR_CPU_COMPARE_ERROR:
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VIR_ALLOC(guest) < 0 || !(guest->arch = strdup(ut->machine)))
|
||||||
|
goto no_memory;
|
||||||
|
|
||||||
|
if (cpuDecode(conn, guest, data, ncpus, cpus) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
virBufferVSprintf(&buf, "%s", guest->model);
|
||||||
|
for (i = 0; i < guest->nfeatures; i++)
|
||||||
|
virBufferVSprintf(&buf, ",+%s", guest->features[i].name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* Need to force a 32-bit guest CPU type if
|
||||||
|
*
|
||||||
|
* 1. guest OS is i686
|
||||||
|
* 2. host OS is x86_64
|
||||||
|
* 3. emulator is qemu-kvm or kvm
|
||||||
|
*
|
||||||
|
* Or
|
||||||
|
*
|
||||||
|
* 1. guest OS is i686
|
||||||
|
* 2. emulator is qemu-system-x86_64
|
||||||
|
*/
|
||||||
|
if (STREQ(def->os.arch, "i686") &&
|
||||||
|
((STREQ(ut->machine, "x86_64") &&
|
||||||
|
strstr(emulator, "kvm")) ||
|
||||||
|
strstr(emulator, "x86_64")))
|
||||||
|
virBufferAddLit(&buf, "qemu32");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virBufferError(&buf))
|
||||||
|
goto no_memory;
|
||||||
|
|
||||||
|
*opt = virBufferContentAndReset(&buf);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virCPUDefFree(guest);
|
||||||
|
cpuDataFree(conn, ut->machine, data);
|
||||||
|
|
||||||
|
if (cpus) {
|
||||||
|
for (i = 0; i < ncpus; i++)
|
||||||
|
VIR_FREE(cpus[i]);
|
||||||
|
VIR_FREE(cpus);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
no_memory:
|
||||||
|
virReportOOMError(conn);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define QEMU_SERIAL_PARAM_ACCEPTED_CHARS \
|
#define QEMU_SERIAL_PARAM_ACCEPTED_CHARS \
|
||||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
|
||||||
|
|
||||||
@ -1610,7 +1906,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
|
|||||||
const char *emulator;
|
const char *emulator;
|
||||||
char uuid[VIR_UUID_STRING_BUFLEN];
|
char uuid[VIR_UUID_STRING_BUFLEN];
|
||||||
char domid[50];
|
char domid[50];
|
||||||
const char *cpu = NULL;
|
char *cpu;
|
||||||
|
|
||||||
uname_normalize(&ut);
|
uname_normalize(&ut);
|
||||||
|
|
||||||
@ -1670,24 +1966,6 @@ int qemudBuildCommandLine(virConnectPtr conn,
|
|||||||
def->virtType == VIR_DOMAIN_VIRT_KVM)
|
def->virtType == VIR_DOMAIN_VIRT_KVM)
|
||||||
enableKVM = 1;
|
enableKVM = 1;
|
||||||
|
|
||||||
/*
|
|
||||||
* Need to force a 32-bit guest CPU type if
|
|
||||||
*
|
|
||||||
* 1. guest OS is i686
|
|
||||||
* 2. host OS is x86_64
|
|
||||||
* 3. emulator is qemu-kvm or kvm
|
|
||||||
*
|
|
||||||
* Or
|
|
||||||
*
|
|
||||||
* 1. guest OS is i686
|
|
||||||
* 2. emulator is qemu-system-x86_64
|
|
||||||
*/
|
|
||||||
if (STREQ(def->os.arch, "i686") &&
|
|
||||||
((STREQ(ut.machine, "x86_64") &&
|
|
||||||
strstr(emulator, "kvm")) ||
|
|
||||||
strstr(emulator, "x86_64")))
|
|
||||||
cpu = "qemu32";
|
|
||||||
|
|
||||||
#define ADD_ARG_SPACE \
|
#define ADD_ARG_SPACE \
|
||||||
do { \
|
do { \
|
||||||
if (qargc == qarga) { \
|
if (qargc == qarga) { \
|
||||||
@ -1788,9 +2066,14 @@ int qemudBuildCommandLine(virConnectPtr conn,
|
|||||||
ADD_ARG_LIT("-M");
|
ADD_ARG_LIT("-M");
|
||||||
ADD_ARG_LIT(def->os.machine);
|
ADD_ARG_LIT(def->os.machine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qemudBuildCommandLineCPU(conn, driver, def, emulator, &ut, &cpu) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (cpu) {
|
if (cpu) {
|
||||||
ADD_ARG_LIT("-cpu");
|
ADD_ARG_LIT("-cpu");
|
||||||
ADD_ARG_LIT(cpu);
|
ADD_ARG_LIT(cpu);
|
||||||
|
VIR_FREE(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disableKQEMU)
|
if (disableKQEMU)
|
||||||
@ -3429,6 +3712,79 @@ error:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuParseCommandLineCPU(virConnectPtr conn,
|
||||||
|
virDomainDefPtr dom,
|
||||||
|
const char *val)
|
||||||
|
{
|
||||||
|
virCPUDefPtr cpu;
|
||||||
|
const char *p = val;
|
||||||
|
const char *next;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(cpu) < 0)
|
||||||
|
goto no_memory;
|
||||||
|
|
||||||
|
cpu->type = VIR_CPU_TYPE_GUEST;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (*p == '\0' || *p == ',')
|
||||||
|
goto syntax;
|
||||||
|
|
||||||
|
if ((next = strchr(p, ',')))
|
||||||
|
next++;
|
||||||
|
|
||||||
|
if (!cpu->model) {
|
||||||
|
if (next)
|
||||||
|
cpu->model = strndup(p, next - p - 1);
|
||||||
|
else
|
||||||
|
cpu->model = strdup(p);
|
||||||
|
|
||||||
|
if (!cpu->model)
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
|
else if (*p == '+' || *p == '-') {
|
||||||
|
char *feature;
|
||||||
|
int policy;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (*p == '+')
|
||||||
|
policy = VIR_CPU_FEATURE_REQUIRE;
|
||||||
|
else
|
||||||
|
policy = VIR_CPU_FEATURE_DISABLE;
|
||||||
|
|
||||||
|
p++;
|
||||||
|
if (*p == '\0' || *p == ',')
|
||||||
|
goto syntax;
|
||||||
|
|
||||||
|
if (next)
|
||||||
|
feature = strndup(p, next - p - 1);
|
||||||
|
else
|
||||||
|
feature = strdup(p);
|
||||||
|
|
||||||
|
ret = virCPUDefAddFeature(conn, cpu, feature, policy);
|
||||||
|
VIR_FREE(feature);
|
||||||
|
if (ret < 0)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} while ((p = next));
|
||||||
|
|
||||||
|
dom->cpu = cpu;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
syntax:
|
||||||
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("unknown CPU syntax '%s'"), val);
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
no_memory:
|
||||||
|
virReportOOMError(conn);
|
||||||
|
error:
|
||||||
|
virCPUDefFree(cpu);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Analyse the env and argv settings and reconstruct a
|
* Analyse the env and argv settings and reconstruct a
|
||||||
* virDomainDefPtr representing these settings as closely
|
* virDomainDefPtr representing these settings as closely
|
||||||
@ -3856,6 +4212,10 @@ virDomainDefPtr qemuParseCommandLine(virConnectPtr conn,
|
|||||||
_("unknown video adapter type '%s'"), val);
|
_("unknown video adapter type '%s'"), val);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
} else if (STREQ(arg, "-cpu")) {
|
||||||
|
WANT_VALUE();
|
||||||
|
if (qemuParseCommandLineCPU(conn, def, val) < 0)
|
||||||
|
goto error;
|
||||||
} else if (STREQ(arg, "-domid")) {
|
} else if (STREQ(arg, "-domid")) {
|
||||||
WANT_VALUE();
|
WANT_VALUE();
|
||||||
/* ignore, generted on the fly */
|
/* ignore, generted on the fly */
|
||||||
|
@ -37,6 +37,8 @@
|
|||||||
#include "security/security_driver.h"
|
#include "security/security_driver.h"
|
||||||
#include "cgroup.h"
|
#include "cgroup.h"
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
|
#include "cpu_conf.h"
|
||||||
|
#include "driver.h"
|
||||||
|
|
||||||
#define qemudDebug(fmt, ...) do {} while(0)
|
#define qemudDebug(fmt, ...) do {} while(0)
|
||||||
|
|
||||||
@ -203,6 +205,11 @@ int qemudProbeMachineTypes (const char *binary,
|
|||||||
virCapsGuestMachinePtr **machines,
|
virCapsGuestMachinePtr **machines,
|
||||||
int *nmachines);
|
int *nmachines);
|
||||||
|
|
||||||
|
int qemudProbeCPUModels (const char *qemu,
|
||||||
|
const char *arch,
|
||||||
|
unsigned int *count,
|
||||||
|
const char ***cpus);
|
||||||
|
|
||||||
int qemudCanonicalizeMachine (struct qemud_driver *driver,
|
int qemudCanonicalizeMachine (struct qemud_driver *driver,
|
||||||
virDomainDefPtr def);
|
virDomainDefPtr def);
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
#include "cgroup.h"
|
#include "cgroup.h"
|
||||||
#include "libvirt_internal.h"
|
#include "libvirt_internal.h"
|
||||||
#include "xml.h"
|
#include "xml.h"
|
||||||
|
#include "cpu/cpu.h"
|
||||||
|
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_QEMU
|
#define VIR_FROM_THIS VIR_FROM_QEMU
|
||||||
@ -2844,24 +2845,19 @@ static int qemudGetMaxVCPUs(virConnectPtr conn, const char *type) {
|
|||||||
|
|
||||||
static char *qemudGetCapabilities(virConnectPtr conn) {
|
static char *qemudGetCapabilities(virConnectPtr conn) {
|
||||||
struct qemud_driver *driver = conn->privateData;
|
struct qemud_driver *driver = conn->privateData;
|
||||||
virCapsPtr caps;
|
virCapsPtr caps = NULL;
|
||||||
char *xml = NULL;
|
char *xml = NULL;
|
||||||
|
|
||||||
qemuDriverLock(driver);
|
qemuDriverLock(driver);
|
||||||
if ((caps = qemudCapsInit(qemu_driver->caps)) == NULL) {
|
if ((caps = qemudCapsInit(qemu_driver->caps)) == NULL)
|
||||||
virReportOOMError(conn);
|
goto no_memory;
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
caps->privateDataAllocFunc = qemuDomainObjPrivateAlloc;
|
caps->privateDataAllocFunc = qemuDomainObjPrivateAlloc;
|
||||||
caps->privateDataFreeFunc = qemuDomainObjPrivateFree;
|
caps->privateDataFreeFunc = qemuDomainObjPrivateFree;
|
||||||
|
|
||||||
if (qemu_driver->securityDriver &&
|
if (qemu_driver->securityDriver &&
|
||||||
qemudSecurityCapsInit(qemu_driver->securityDriver, caps) < 0) {
|
qemudSecurityCapsInit(qemu_driver->securityDriver, caps) < 0)
|
||||||
virCapabilitiesFree(caps);
|
goto no_memory;
|
||||||
virReportOOMError(conn);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
virCapabilitiesFree(qemu_driver->caps);
|
virCapabilitiesFree(qemu_driver->caps);
|
||||||
qemu_driver->caps = caps;
|
qemu_driver->caps = caps;
|
||||||
@ -2873,6 +2869,11 @@ cleanup:
|
|||||||
qemuDriverUnlock(driver);
|
qemuDriverUnlock(driver);
|
||||||
|
|
||||||
return xml;
|
return xml;
|
||||||
|
|
||||||
|
no_memory:
|
||||||
|
virCapabilitiesFree(caps);
|
||||||
|
virReportOOMError(conn);
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -7849,6 +7850,28 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuCPUCompare(virConnectPtr conn,
|
||||||
|
const char *xmlDesc,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
struct qemud_driver *driver = conn->privateData;
|
||||||
|
int ret = VIR_CPU_COMPARE_ERROR;
|
||||||
|
|
||||||
|
qemuDriverLock(driver);
|
||||||
|
|
||||||
|
if (!driver->caps || !driver->caps->host.cpu) {
|
||||||
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
|
||||||
|
"%s", _("cannot get host CPU capabilities"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = cpuCompareXML(conn, driver->caps->host.cpu, xmlDesc);
|
||||||
|
|
||||||
|
qemuDriverUnlock(driver);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static virDriver qemuDriver = {
|
static virDriver qemuDriver = {
|
||||||
VIR_DRV_QEMU,
|
VIR_DRV_QEMU,
|
||||||
"QEMU",
|
"QEMU",
|
||||||
@ -7923,7 +7946,7 @@ static virDriver qemuDriver = {
|
|||||||
qemuIsSecure,
|
qemuIsSecure,
|
||||||
qemuDomainIsActive,
|
qemuDomainIsActive,
|
||||||
qemuDomainIsPersistent,
|
qemuDomainIsPersistent,
|
||||||
NULL, /* cpuCompare */
|
qemuCPUCompare, /* cpuCompare */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user