qemu: Build command line for ivshmem device

This patch implements support for the ivshmem device in QEMU.

Signed-off-by: Maxime Leroy <maxime.leroy@6wind.com>
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
This commit is contained in:
Martin Kletzander 2014-09-25 09:00:47 +02:00
parent e3d478eb51
commit b90a9a6374
6 changed files with 188 additions and 2 deletions

View File

@ -9758,7 +9758,7 @@ virDomainShmemDefParseXML(xmlNodePtr node,
1, ULLONG_MAX, false) < 0)
goto cleanup;
if ((server = virXPathNode("./server", ctxt))) {
if ((server = virXPathNode("./server[1]", ctxt))) {
def->server.enabled = true;
if ((tmp = virXMLPropString(server, "path")))
@ -9766,7 +9766,7 @@ virDomainShmemDefParseXML(xmlNodePtr node,
VIR_FREE(tmp);
}
if ((msi = virXPathNode("./msi", ctxt))) {
if ((msi = virXPathNode("./msi[1]", ctxt))) {
def->msi.enabled = true;
if ((tmp = virXMLPropString(msi, "vectors")) &&

View File

@ -1029,6 +1029,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
if (virAsprintf(&def->hubs[i]->info.alias, "hub%zu", i) < 0)
return -1;
}
for (i = 0; i < def->nshmems; i++) {
if (virAsprintf(&def->shmems[i]->info.alias, "shmem%zu", i) < 0)
return -1;
}
for (i = 0; i < def->nsmartcards; i++) {
if (virAsprintf(&def->smartcards[i]->info.alias, "smartcard%zu", i) < 0)
return -1;
@ -7525,6 +7529,114 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
return ret;
}
static int
qemuBuildShmemDevCmd(virCommandPtr cmd,
virDomainDefPtr def,
virDomainShmemDefPtr shmem,
virQEMUCapsPtr qemuCaps)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IVSHMEM)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("ivshmem device is not supported "
"with this QEMU binary"));
goto error;
}
virBufferAddLit(&buf, "ivshmem");
if (shmem->size) {
/*
* Thanks to our parsing code, we have a guarantee that the
* size is power of two and is at least a mebibyte in size.
* But because it may change inthe future, the checks are
* doubled in here.
*/
if (shmem->size & (shmem->size - 1)) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("shmem size must be a power of two"));
goto error;
}
if (shmem->size < 1024 * 1024) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("shmem size must be at least 1 MiB"));
goto error;
}
virBufferAsprintf(&buf, ",size=%llum",
VIR_DIV_UP(shmem->size, 1024 * 1024));
}
if (!shmem->server.enabled) {
virBufferAsprintf(&buf, ",shm=%s", shmem->name);
} else {
virBufferAsprintf(&buf, ",chardev=char%s", shmem->info.alias);
if (shmem->msi.enabled) {
virBufferAddLit(&buf, ",msi=on");
if (shmem->msi.vectors)
virBufferAsprintf(&buf, ",vectors=%u", shmem->msi.vectors);
if (shmem->msi.ioeventfd)
virBufferAsprintf(&buf, ",ioeventfd=%s",
virTristateSwitchTypeToString(shmem->msi.ioeventfd));
}
}
if (qemuBuildDeviceAddressStr(&buf, def, &shmem->info, qemuCaps) < 0)
goto error;
if (virBufferCheckError(&buf) < 0)
goto error;
virCommandAddArg(cmd, "-device");
virCommandAddArgBuffer(cmd, &buf);
return 0;
error:
virBufferFreeAndReset(&buf);
return -1;
}
static int
qemuBuildShmemCommandLine(virCommandPtr cmd,
virDomainDefPtr def,
virDomainShmemDefPtr shmem,
virQEMUCapsPtr qemuCaps)
{
if (qemuBuildShmemDevCmd(cmd, def, shmem, qemuCaps) < 0)
return -1;
if (shmem->server.enabled) {
char *devstr = NULL;
virDomainChrSourceDef source = {
.type = VIR_DOMAIN_CHR_TYPE_UNIX,
.data.nix = {
.path = shmem->server.path,
.listen = false,
}
};
if (!shmem->server.path &&
virAsprintf(&source.data.nix.path,
"/var/lib/libvirt/shmem-%s-sock",
shmem->name) < 0)
return -1;
devstr = qemuBuildChrChardevStr(&source, shmem->info.alias, qemuCaps);
if (!shmem->server.path)
VIR_FREE(source.data.nix.path);
if (!devstr)
return -1;
virCommandAddArg(cmd, "-chardev");
virCommandAddArg(cmd, devstr);
VIR_FREE(devstr);
}
return 0;
}
static int
qemuBuildChrDeviceCommandLine(virCommandPtr cmd,
virDomainDefPtr def,
@ -9720,6 +9832,11 @@ qemuBuildCommandLine(virConnectPtr conn,
}
}
for (i = 0; i < def->nshmems; i++) {
if (qemuBuildShmemCommandLine(cmd, def, def->shmems[i], qemuCaps))
goto error;
}
if (mlock) {
unsigned long long memKB;

View File

@ -0,0 +1,24 @@
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory unit='KiB'>219136</memory>
<currentMemory unit='KiB'>219136</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu</emulator>
<controller type='usb' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='none'/>
<shmem name='shmem0'>
<size unit='K'>12345</size>
</shmem>
</devices>
</domain>

View File

@ -0,0 +1,24 @@
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory unit='KiB'>219136</memory>
<currentMemory unit='KiB'>219136</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu</emulator>
<controller type='usb' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='none'/>
<shmem name='shmem0'>
<size unit='K'>16</size>
</shmem>
</devices>
</domain>

View File

@ -0,0 +1,16 @@
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
/usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefaults \
-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \
-device ivshmem,shm=shmem0 \
-device ivshmem,size=128m,shm=shmem1 \
-device ivshmem,size=256m,shm=shmem2 \
-device ivshmem,size=512m,chardev=charshmem3 \
-chardev socket,id=charshmem3,path=/var/lib/libvirt/shmem-shmem3-sock \
-device ivshmem,size=1024m,chardev=charshmem4 \
-chardev socket,id=charshmem4,path=/tmp/shmem4-sock \
-device ivshmem,size=2048m,chardev=charshmem5,msi=on,ioeventfd=off \
-chardev socket,id=charshmem5,path=/tmp/shmem5-sock \
-device ivshmem,size=4096m,chardev=charshmem6,msi=on,vectors=16 \
-chardev socket,id=charshmem6,path=/tmp/shmem6-sock \
-device ivshmem,size=8192m,chardev=charshmem7,msi=on,vectors=32,ioeventfd=on \
-chardev socket,id=charshmem7,path=/tmp/shmem7-sock

View File

@ -1466,6 +1466,11 @@ mymain(void)
DO_TEST("fips-enabled", QEMU_CAPS_ENABLE_FIPS);
DO_TEST("shmem", QEMU_CAPS_PCIDEVICE,
QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_IVSHMEM);
DO_TEST_FAILURE("shmem", NONE);
DO_TEST_FAILURE("shmem-invalid-size", NONE);
DO_TEST_FAILURE("shmem-small-size", NONE);
DO_TEST_PARSE_ERROR("shmem-msi-only", NONE);
virObjectUnref(driver.config);