The following patch fixes some problems on powerpc Linux machines when
trying to start an x86-based VM using qemu.
In the order as the hunks appear the fix the following problems:
- Qemu on (my) powerpc machine for some reason takes a long time for it
to create its UnixIO socket. It's like 9 seconds or so and probably more
once on a busy system. So increase the timeout for waiting for that
socket to appear.
- VM saved images written on an x86 host have a header in little endian
format. So, when checking the 32 bit int for the header version and if
the version is out-of-range swap the endianess of the header and try
again and only then fail. This also then works when the big endian host
has written the header in big endian format and now the VM is supposed
to resume on a little endina host.
- Setting the CPU affinity doesn't seem to work at all on (my) PPC host.
So rather than failing the start of a VM when nodeGetInfo/virNodeGetInfo
fail, make the setting of the CPU affinity pass on powerpc machines so
the VM at least starts.
Signed-off-by: Stefan Berger <stefanb(a)linux.vnet.ibm.com>
---
src/qemu/qemu_driver.c | 15 +++++++++++++++
src/qemu/qemu_monitor.c | 4 ++++
src/qemu/qemu_process.c | 10 +++++++++-
3 files changed, 28 insertions(+), 1 deletion(-)
Index: libvirt/src/qemu/qemu_monitor.c
===================================================================
--- libvirt.orig/src/qemu/qemu_monitor.c
+++ libvirt/src/qemu/qemu_monitor.c
@@ -249,7 +249,11 @@ qemuMonitorOpenUnix(const char *monitor)
{
struct sockaddr_un addr;
int monfd;
+#if defined(__powerpc64__) || defined(__powerpc__)
+ int timeout = 30; /* In seconds */
+#else
int timeout = 3; /* In seconds */
+#endif
int ret, i = 0;
if ((monfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
Index: libvirt/src/qemu/qemu_driver.c
===================================================================
--- libvirt.orig/src/qemu/qemu_driver.c
+++ libvirt/src/qemu/qemu_driver.c
@@ -43,6 +43,7 @@
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/un.h>
+#include <byteswap.h>
#include "qemu_driver.h"
@@ -1882,6 +1883,15 @@ struct qemud_save_header {
int unused[15];
};
+static inline void
+bswap_header(struct qemud_save_header *hdr) {
+ hdr->version = bswap_32(hdr->version);
+ hdr->xml_len = bswap_32(hdr->xml_len);
+ hdr->was_running = bswap_32(hdr->was_running);
+ hdr->compressed = bswap_32(hdr->compressed);
+}
+
+
/* return -errno on failure, or 0 on success */
static int
qemuDomainSaveHeader(int fd, const char *path, char *xml,
@@ -3091,6 +3101,11 @@ qemuDomainSaveImageOpen(struct qemud_dri
}
if (header.version > QEMUD_SAVE_VERSION) {
+ /* try to convert endianess */
+ bswap_header(&header);
+ }
+
+ if (header.version > QEMUD_SAVE_VERSION) {
qemuReportError(VIR_ERR_OPERATION_FAILED,
_("image version is not supported (%d > %d)"),
header.version, QEMUD_SAVE_VERSION);
Index: libvirt/src/qemu/qemu_process.c
===================================================================
--- libvirt.orig/src/qemu/qemu_process.c
+++ libvirt/src/qemu/qemu_process.c
@@ -1239,7 +1239,11 @@ qemuProcessInitCpuAffinity(virDomainObjP
VIR_DEBUG0("Setting CPU affinity");
if (nodeGetInfo(NULL, &nodeinfo) < 0)
+#if defined (__powerpc64__) || defined (__powerpc__)
+ return 0;
+#else
return -1;
+#endif
/* setaffinity fails if you set bits for CPUs which
* aren't present, so we have to limit ourselves */
@@ -1295,7 +1299,11 @@ qemuProcessSetVcpuAffinites(virConnectPt
int vcpu, cpumaplen, hostcpus, maxcpu;
if (virNodeGetInfo(conn, &nodeinfo) != 0) {
- return -1;
+#if defined (__powerpc64__) || defined (__powerpc__)
+ return 0;
+#else
+ return -1;
+#endif
}
if (!def->cputune.nvcpupin)