]> xenbits.xensource.com Git - libvirt.git/commitdiff
* src/xen_internal.c: try to autodetect the Xen hypervisor version
authorDaniel Veillard <veillard@redhat.com>
Wed, 21 Jun 2006 12:15:18 +0000 (12:15 +0000)
committerDaniel Veillard <veillard@redhat.com>
Wed, 21 Jun 2006 12:15:18 +0000 (12:15 +0000)
  used and switch automatically. A bit nasty though.
Daniel

ChangeLog
src/xen_internal.c

index 50b91f993079bc42443eaf672c972b3949b76f01..aa520a49e84bcd0368fac49117fdc3a4fdb3cbe2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Wed Jun 21 12:23:15 EDT 2006 Daniel Veillard <veillard@redhat.com>
+
+       * src/xen_internal.c: try to autodetect the Xen hypervisor version
+         used and switch automatically. A bit nasty though.
+
 Tue Jun 20 16:14:26 EDT 2006 Daniel Veillard <veillard@redhat.com>
 
        * src/xen_internal.c: fix breakage introduced in Xen changeset 10277
index e56a3b920bbb71bf446e434d596568640e286c28..209265bf6d863dc5d11a8e642ad53cf82a6392fe 100644 (file)
 #include <xen/xen.h>
 #include <xen/linux/privcmd.h>
 
-#if 0
 /* #ifndef __LINUX_PUBLIC_PRIVCMD_H__ */
-typedef struct hypercall_struct {
-    __u64 op;
-    __u64 arg[5];
-} hypercall_t;
-#define XEN_IOCTL_HYPERCALL_CMD _IOC(_IOC_NONE, 'P', 0, sizeof(hypercall_t))
-#else
+typedef struct old_hypercall_struct {
+    unsigned long op;
+    unsigned long arg[5];
+} old_hypercall_t;
+#define XEN_OLD_IOCTL_HYPERCALL_CMD \
+        _IOC(_IOC_NONE, 'P', 0, sizeof(old_hypercall_t))
+
 typedef struct privcmd_hypercall hypercall_t;
 #define XEN_IOCTL_HYPERCALL_CMD IOCTL_PRIVCMD_HYPERCALL
-#endif
 
+static int xen_ioctl_hypercall_cmd = 0;
+static int old_hypervisor = 0;
+static int initialized = 0;
+static int hv_version = 0;
 
 #include "internal.h"
 #include "driver.h"
@@ -48,13 +51,14 @@ typedef struct privcmd_hypercall hypercall_t;
 
 static const char * xenHypervisorGetType(virConnectPtr conn);
 static unsigned long xenHypervisorGetMaxMemory(virDomainPtr domain);
+static int xenHypervisorInit(void);
 
 static virDriver xenHypervisorDriver = {
     "Xen",
     (DOM0_INTERFACE_VERSION >> 24) * 1000000 +
     ((DOM0_INTERFACE_VERSION >> 16) & 0xFF) * 1000 +
     (DOM0_INTERFACE_VERSION & 0xFFFF),
-    NULL, /* init */
+    xenHypervisorInit, /* init */
     xenHypervisorOpen, /* open */
     xenHypervisorClose, /* close */
     xenHypervisorGetType, /* type */
@@ -84,16 +88,6 @@ static virDriver xenHypervisorDriver = {
     NULL /* domainRestore */
 };
 
-/**
- * xenHypervisorRegister:
- *
- * Registers the xenHypervisor driver
- */
-void xenHypervisorRegister(void)
-{
-    virRegisterDriver(&xenHypervisorDriver);
-}
-
 /**
  * virXenError:
  * @conn: the connection if available
@@ -115,6 +109,84 @@ virXenError(virErrorNumber error, const char *info, int value)
                     errmsg, info, NULL, value, 0, errmsg, info, value);
 }
 
+/**
+ * xenHypervisorInit:
+ *
+ * Initialize the hypervisor layer. Try to detect the kind of interface
+ * used i.e. pre or post changeset 10277
+ */
+int xenHypervisorInit(void)
+{
+    int fd, ret, cmd;
+    hypercall_t hc;
+    old_hypercall_t old_hc;
+
+    if (initialized) {
+        if (old_hypervisor == -1)
+           return(-1);
+       return(0);
+    }
+    initialized = 1;
+
+    ret = open(XEN_HYPERVISOR_SOCKET, O_RDWR);
+    if (ret < 0) {
+       old_hypervisor = -1;
+        return (-1);
+    }
+    fd = ret;
+
+    hc.op = __HYPERVISOR_xen_version;
+    hc.arg[0] = (unsigned long) XENVER_version;
+    hc.arg[1] = 0;
+
+    cmd = IOCTL_PRIVCMD_HYPERCALL;
+    ret = ioctl(fd, cmd, (unsigned long) &hc);
+
+    if ((ret != -1) && (ret != 0)) {
+        fprintf(stderr, "Using new hypervisor call: %X\n", ret);
+       hv_version = ret;
+       xen_ioctl_hypercall_cmd = cmd;
+        old_hypervisor = 0;
+       goto done;
+    }
+    
+    old_hc.op = __HYPERVISOR_xen_version;
+    old_hc.arg[0] = (unsigned long) XENVER_version;
+    old_hc.arg[1] = 0;
+    cmd = _IOC(_IOC_NONE, 'P', 0, sizeof(old_hypercall_t));
+    ret = ioctl(fd, cmd, (unsigned long) &old_hc);
+    if ((ret != -1) && (ret != 0)) {
+        fprintf(stderr, "Using old hypervisor call: %X\n", ret);
+       hv_version = ret;
+       xen_ioctl_hypercall_cmd = cmd;
+        old_hypervisor = 1;
+       goto done;
+    }
+
+    old_hypervisor = -1;
+    virXenError(VIR_ERR_XEN_CALL, " ioctl ", IOCTL_PRIVCMD_HYPERCALL);
+    close(fd);
+    return(-1);
+
+done:
+    close(fd);
+    return(0);
+
+}
+
+/**
+ * xenHypervisorRegister:
+ *
+ * Registers the xenHypervisor driver
+ */
+void xenHypervisorRegister(void)
+{
+    if (initialized == 0)
+        xenHypervisorInit();
+
+    virRegisterDriver(&xenHypervisorDriver);
+}
+
 /**
  * xenHypervisorOpen:
  * @conn: pointer to the connection block
@@ -130,6 +202,9 @@ xenHypervisorOpen(virConnectPtr conn, const char *name, int flags)
 {
     int ret;
 
+    if (initialized == 0)
+        xenHypervisorInit();
+
     if ((name != NULL) && (strcasecmp(name, "xen")))
         return(-1);
 
@@ -168,6 +243,47 @@ xenHypervisorClose(virConnectPtr conn)
     return (0);
 }
 
+/**
+ * xenHypervisorDoOldOp:
+ * @handle: the handle to the Xen hypervisor
+ * @op: pointer to the hyperviros operation structure
+ *
+ * Do an hypervisor operation though the old interface,
+ * this leads to an hypervisor call through ioctl.
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+static int
+xenHypervisorDoOldOp(int handle, dom0_op_t * op)
+{
+    int ret;
+    old_hypercall_t hc;
+
+    memset(&hc, 0, sizeof(hc));
+    op->interface_version = hv_version << 8;
+    hc.op = __HYPERVISOR_dom0_op;
+    hc.arg[0] = (unsigned long) op;
+
+    if (mlock(op, sizeof(dom0_op_t)) < 0) {
+        virXenError(VIR_ERR_XEN_CALL, " locking", sizeof(dom0_op_t));
+        return (-1);
+    }
+
+    ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
+    if (ret < 0) {
+        virXenError(VIR_ERR_XEN_CALL, " ioctl ", xen_ioctl_hypercall_cmd);
+    }
+
+    if (munlock(op, sizeof(dom0_op_t)) < 0) {
+        virXenError(VIR_ERR_XEN_CALL, " releasing", sizeof(dom0_op_t));
+        ret = -1;
+    }
+
+    if (ret < 0)
+        return (-1);
+
+    return (0);
+}
 /**
  * xenHypervisorDoOp:
  * @handle: the handle to the Xen hypervisor
@@ -181,9 +297,12 @@ static int
 xenHypervisorDoOp(int handle, dom0_op_t * op)
 {
     int ret;
-    unsigned int cmd;
     hypercall_t hc;
 
+    if (old_hypervisor)
+        return(xenHypervisorDoOldOp(handle, op));
+    memset(&hc, 0, sizeof(hc));
     op->interface_version = DOM0_INTERFACE_VERSION;
     hc.op = __HYPERVISOR_dom0_op;
     hc.arg[0] = (unsigned long) op;
@@ -193,10 +312,9 @@ xenHypervisorDoOp(int handle, dom0_op_t * op)
         return (-1);
     }
 
-    cmd = XEN_IOCTL_HYPERCALL_CMD;
-    ret = ioctl(handle, cmd, (unsigned long) &hc);
+    ret = ioctl(handle, xen_ioctl_hypercall_cmd, (unsigned long) &hc);
     if (ret < 0) {
-        virXenError(VIR_ERR_XEN_CALL, " ioctl ", cmd);
+        virXenError(VIR_ERR_XEN_CALL, " ioctl ", xen_ioctl_hypercall_cmd);
     }
 
     if (munlock(op, sizeof(dom0_op_t)) < 0) {
@@ -242,26 +360,9 @@ xenHypervisorGetType(virConnectPtr conn)
 int
 xenHypervisorGetVersion(virConnectPtr conn, unsigned long *hvVer)
 {
-    int ret;
-    unsigned int cmd;
-    hypercall_t hc;
-
     if ((conn == NULL) || (conn->handle < 0) || (hvVer == NULL))
         return (-1);
-    *hvVer = 0;
-
-    hc.op = __HYPERVISOR_xen_version;
-    hc.arg[0] = (unsigned long) XENVER_version;
-    hc.arg[1] = 0;
-
-    cmd = XEN_IOCTL_HYPERCALL_CMD;
-    ret = ioctl(conn->handle, cmd, (unsigned long) &hc);
-
-    if (ret < 0) {
-        virXenError(VIR_ERR_XEN_CALL, " getting version ", XENVER_version);
-        return (-1);
-    }
-    *hvVer = (ret >> 16) * 1000000 + (ret & 0xFFFF) * 1000;
+    *hvVer = (hv_version >> 16) * 1000000 + (hv_version & 0xFFFF) * 1000;
     return(0);
 }