mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-01 01:15:19 +00:00
qemu: parse and create -cpu ...,-kvmclock
QEMU supports a bunch of CPUID features that are tied to the kvm CPUID nodes rather than the processor's. They are "kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvm_asyncpf". These are not known to libvirt and their CPUID leaf might move if (for example) the Hyper-V extensions are enabled. Hence their handling would anyway require some special-casing. However, among these the most useful is kvmclock; an additional "property" of this feature is that a <timer> element is a better model than a CPUID feature. Although, creating part of the -cpu command-line from something other than the <cpu> XML element introduces some ugliness. Reviewed-by: Jiri Denemark <jdenemar@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
5a137f3620
commit
b66d1bef14
@ -3500,7 +3500,9 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
|
|||||||
virCPUDefPtr cpu = NULL;
|
virCPUDefPtr cpu = NULL;
|
||||||
unsigned int ncpus = 0;
|
unsigned int ncpus = 0;
|
||||||
const char **cpus = NULL;
|
const char **cpus = NULL;
|
||||||
|
const char *default_model;
|
||||||
union cpuData *data = NULL;
|
union cpuData *data = NULL;
|
||||||
|
bool have_cpu = false;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
int i;
|
int i;
|
||||||
@ -3517,6 +3519,11 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (STREQ(def->os.arch, "i686"))
|
||||||
|
default_model = "qemu32";
|
||||||
|
else
|
||||||
|
default_model = "qemu64";
|
||||||
|
|
||||||
if (cpu) {
|
if (cpu) {
|
||||||
virCPUCompareResult cmp;
|
virCPUCompareResult cmp;
|
||||||
const char *preferred;
|
const char *preferred;
|
||||||
@ -3594,6 +3601,7 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
|
|||||||
virBufferAsprintf(&buf, ",%c%s", sign, guest->features[i].name);
|
virBufferAsprintf(&buf, ",%c%s", sign, guest->features[i].name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
have_cpu = true;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Need to force a 32-bit guest CPU type if
|
* Need to force a 32-bit guest CPU type if
|
||||||
@ -3610,8 +3618,26 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
|
|||||||
if (STREQ(def->os.arch, "i686") &&
|
if (STREQ(def->os.arch, "i686") &&
|
||||||
((STREQ(ut->machine, "x86_64") &&
|
((STREQ(ut->machine, "x86_64") &&
|
||||||
strstr(emulator, "kvm")) ||
|
strstr(emulator, "kvm")) ||
|
||||||
strstr(emulator, "x86_64")))
|
strstr(emulator, "x86_64"))) {
|
||||||
virBufferAddLit(&buf, "qemu32");
|
virBufferAdd(&buf, default_model, -1);
|
||||||
|
have_cpu = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now force kvmclock on/off based on the corresponding <timer> element. */
|
||||||
|
for (i = 0; i < def->clock.ntimers; i++) {
|
||||||
|
if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK &&
|
||||||
|
def->clock.timers[i]->present != -1) {
|
||||||
|
char sign;
|
||||||
|
if (def->clock.timers[i]->present)
|
||||||
|
sign = '+';
|
||||||
|
else
|
||||||
|
sign = '-';
|
||||||
|
virBufferAsprintf(&buf, "%s,%ckvmclock",
|
||||||
|
have_cpu ? "" : default_model,
|
||||||
|
sign);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virBufferError(&buf))
|
if (virBufferError(&buf))
|
||||||
@ -4091,6 +4117,10 @@ qemuBuildCommandLine(virConnectPtr conn,
|
|||||||
virDomainTimerNameTypeToString(def->clock.timers[i]->name));
|
virDomainTimerNameTypeToString(def->clock.timers[i]->name));
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_TIMER_NAME_KVMCLOCK:
|
||||||
|
/* This is handled when building -cpu. */
|
||||||
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_TIMER_NAME_RTC:
|
case VIR_DOMAIN_TIMER_NAME_RTC:
|
||||||
/* This has already been taken care of (in qemuBuildClockArgStr)
|
/* This has already been taken care of (in qemuBuildClockArgStr)
|
||||||
if QEMU_CAPS_RTC is set (mutually exclusive with
|
if QEMU_CAPS_RTC is set (mutually exclusive with
|
||||||
@ -6829,14 +6859,47 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
|
|||||||
if (!feature)
|
if (!feature)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
if (!cpu) {
|
if (STREQ(feature, "kvmclock")) {
|
||||||
if (!(cpu = qemuInitGuestCPU(dom)))
|
bool present = (policy == VIR_CPU_FEATURE_REQUIRE);
|
||||||
goto error;
|
int i;
|
||||||
|
|
||||||
cpu->model = model;
|
for (i = 0; i < dom->clock.ntimers; i++) {
|
||||||
model = NULL;
|
if (dom->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == dom->clock.ntimers) {
|
||||||
|
if (VIR_REALLOC_N(dom->clock.timers, i+1) < 0 ||
|
||||||
|
VIR_ALLOC(dom->clock.timers[i]) < 0)
|
||||||
|
goto no_memory;
|
||||||
|
dom->clock.timers[i]->name = VIR_DOMAIN_TIMER_NAME_KVMCLOCK;
|
||||||
|
dom->clock.timers[i]->present = -1;
|
||||||
|
dom->clock.timers[i]->tickpolicy = -1;
|
||||||
|
dom->clock.timers[i]->track = -1;
|
||||||
|
dom->clock.ntimers++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dom->clock.timers[i]->present != -1 &&
|
||||||
|
dom->clock.timers[i]->present != present) {
|
||||||
|
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("conflicting occurrences of kvmclock feature"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
dom->clock.timers[i]->present = present;
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
if (!cpu) {
|
||||||
|
if (!(cpu = qemuInitGuestCPU(dom)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
cpu->model = model;
|
||||||
|
model = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = virCPUDefAddFeature(cpu, feature, policy);
|
||||||
}
|
}
|
||||||
ret = virCPUDefAddFeature(cpu, feature, policy);
|
|
||||||
VIR_FREE(feature);
|
VIR_FREE(feature);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -144,6 +144,10 @@ mymain(void)
|
|||||||
DO_TEST("boot-cdrom");
|
DO_TEST("boot-cdrom");
|
||||||
DO_TEST("boot-network");
|
DO_TEST("boot-network");
|
||||||
DO_TEST("boot-floppy");
|
DO_TEST("boot-floppy");
|
||||||
|
DO_TEST("kvmclock");
|
||||||
|
/* This needs <emulator>./qemu.sh</emulator> which doesn't work here. */
|
||||||
|
/*DO_TEST("cpu-kvmclock");*/
|
||||||
|
|
||||||
/* Can't roundtrip xenner arch */
|
/* Can't roundtrip xenner arch */
|
||||||
/*DO_TEST("bootloader");*/
|
/*DO_TEST("bootloader");*/
|
||||||
DO_TEST("clock-utc");
|
DO_TEST("clock-utc");
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test ./qemu.sh -S -M pc \
|
||||||
|
-cpu host,-kvmclock -enable-kvm -m 214 -smp 6 \
|
||||||
|
-nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot n -net \
|
||||||
|
none -serial none -parallel none -usb
|
23
tests/qemuxml2argvdata/qemuxml2argv-cpu-host-kvmclock.xml
Normal file
23
tests/qemuxml2argvdata/qemuxml2argv-cpu-host-kvmclock.xml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<domain type='kvm'>
|
||||||
|
<name>QEMUGuest1</name>
|
||||||
|
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||||
|
<memory>219100</memory>
|
||||||
|
<currentMemory>219100</currentMemory>
|
||||||
|
<vcpu>6</vcpu>
|
||||||
|
<os>
|
||||||
|
<type arch='x86_64' machine='pc'>hvm</type>
|
||||||
|
<boot dev='network'/>
|
||||||
|
</os>
|
||||||
|
<cpu mode='host-passthrough'>
|
||||||
|
</cpu>
|
||||||
|
<clock offset='utc'>
|
||||||
|
<timer name='kvmclock' present='no'/>
|
||||||
|
</clock>
|
||||||
|
<on_poweroff>destroy</on_poweroff>
|
||||||
|
<on_reboot>restart</on_reboot>
|
||||||
|
<on_crash>destroy</on_crash>
|
||||||
|
<devices>
|
||||||
|
<emulator>/./qemu.sh</emulator>
|
||||||
|
<memballoon model='virtio'/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
4
tests/qemuxml2argvdata/qemuxml2argv-cpu-kvmclock.args
Normal file
4
tests/qemuxml2argvdata/qemuxml2argv-cpu-kvmclock.args
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test ./qemu.sh -S -M pc \
|
||||||
|
-cpu core2duo,-kvmclock -enable-kvm -m 214 -smp 6 \
|
||||||
|
-nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot n -net \
|
||||||
|
none -serial none -parallel none -usb
|
24
tests/qemuxml2argvdata/qemuxml2argv-cpu-kvmclock.xml
Normal file
24
tests/qemuxml2argvdata/qemuxml2argv-cpu-kvmclock.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<domain type='kvm'>
|
||||||
|
<name>QEMUGuest1</name>
|
||||||
|
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||||
|
<memory>219100</memory>
|
||||||
|
<currentMemory>219100</currentMemory>
|
||||||
|
<vcpu>6</vcpu>
|
||||||
|
<os>
|
||||||
|
<type arch='i686' machine='pc'>hvm</type>
|
||||||
|
<boot dev='network'/>
|
||||||
|
</os>
|
||||||
|
<cpu mode='custom' match='exact'>
|
||||||
|
<model fallback='allow'>core2duo</model>
|
||||||
|
</cpu>
|
||||||
|
<clock offset='utc'>
|
||||||
|
<timer name='kvmclock' present='no'/>
|
||||||
|
</clock>
|
||||||
|
<on_poweroff>destroy</on_poweroff>
|
||||||
|
<on_reboot>restart</on_reboot>
|
||||||
|
<on_crash>destroy</on_crash>
|
||||||
|
<devices>
|
||||||
|
<emulator>/./qemu.sh</emulator>
|
||||||
|
<memballoon model='virtio'/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
4
tests/qemuxml2argvdata/qemuxml2argv-kvmclock.args
Normal file
4
tests/qemuxml2argvdata/qemuxml2argv-kvmclock.args
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/kvm -S -M pc \
|
||||||
|
-cpu qemu32,-kvmclock -m 214 -smp 6 \
|
||||||
|
-nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot n -net \
|
||||||
|
none -serial none -parallel none -usb
|
21
tests/qemuxml2argvdata/qemuxml2argv-kvmclock.xml
Normal file
21
tests/qemuxml2argvdata/qemuxml2argv-kvmclock.xml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<domain type='kvm'>
|
||||||
|
<name>QEMUGuest1</name>
|
||||||
|
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||||
|
<memory>219100</memory>
|
||||||
|
<currentMemory>219100</currentMemory>
|
||||||
|
<vcpu>6</vcpu>
|
||||||
|
<os>
|
||||||
|
<type arch='i686' machine='pc'>hvm</type>
|
||||||
|
<boot dev='network'/>
|
||||||
|
</os>
|
||||||
|
<clock offset='utc'>
|
||||||
|
<timer name='kvmclock' present='no'/>
|
||||||
|
</clock>
|
||||||
|
<on_poweroff>destroy</on_poweroff>
|
||||||
|
<on_reboot>restart</on_reboot>
|
||||||
|
<on_crash>destroy</on_crash>
|
||||||
|
<devices>
|
||||||
|
<emulator>/usr/bin/kvm</emulator>
|
||||||
|
<memballoon model='virtio'/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
@ -385,6 +385,9 @@ mymain(void)
|
|||||||
DO_TEST("clock-variable", false, QEMU_CAPS_RTC);
|
DO_TEST("clock-variable", false, QEMU_CAPS_RTC);
|
||||||
*/
|
*/
|
||||||
DO_TEST("clock-france", false, QEMU_CAPS_RTC);
|
DO_TEST("clock-france", false, QEMU_CAPS_RTC);
|
||||||
|
DO_TEST("cpu-kvmclock", false, QEMU_CAPS_ENABLE_KVM);
|
||||||
|
DO_TEST("cpu-host-kvmclock", false, QEMU_CAPS_ENABLE_KVM, QEMU_CAPS_CPU_HOST);
|
||||||
|
DO_TEST("kvmclock", false, QEMU_CAPS_KVM);
|
||||||
|
|
||||||
DO_TEST("hugepages", false, QEMU_CAPS_MEM_PATH);
|
DO_TEST("hugepages", false, QEMU_CAPS_MEM_PATH);
|
||||||
DO_TEST("disk-cdrom", false, NONE);
|
DO_TEST("disk-cdrom", false, NONE);
|
||||||
|
@ -124,6 +124,9 @@ mymain(void)
|
|||||||
DO_TEST("bootloader");
|
DO_TEST("bootloader");
|
||||||
DO_TEST("clock-utc");
|
DO_TEST("clock-utc");
|
||||||
DO_TEST("clock-localtime");
|
DO_TEST("clock-localtime");
|
||||||
|
DO_TEST("cpu-kvmclock");
|
||||||
|
DO_TEST("cpu-host-kvmclock");
|
||||||
|
DO_TEST("kvmclock");
|
||||||
DO_TEST("hugepages");
|
DO_TEST("hugepages");
|
||||||
DO_TEST("disk-aio");
|
DO_TEST("disk-aio");
|
||||||
DO_TEST("disk-cdrom");
|
DO_TEST("disk-cdrom");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user