]> xenbits.xensource.com Git - libvirt.git/commitdiff
implement capabilities parsing for Solaris
authorJohn Levon <john.levon@sun.com>
Thu, 15 Jan 2009 01:35:17 +0000 (01:35 +0000)
committerJohn Levon <john.levon@sun.com>
Thu, 15 Jan 2009 01:35:17 +0000 (01:35 +0000)
ChangeLog
src/xen_internal.c

index bd4a78178b870b31307e4a59cbb7c144c7dfcd66..6a81db8ec54304e9f82527a131dad8ec41229a3c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Thu Jan 15 01:31:45 GMT 2009  John Levon  <levon@movementarian.org>
+
+       * src/xen_internal.c: implement capabilities parsing for Solaris
+
 Thu Jan 15 01:22:32 GMT 2009  John Levon  <levon@movementarian.org>
 
        * src/xs_internal.c: Fix xs_unwatch() to correctly pass the
index b3a531e3ca65977e14a3b3744afbe7d158da8f63..947cd37dd078a771c9296a76282c0c761798a8d3 100644 (file)
 #endif
 #endif
 
+#ifdef __sun
+#include <sys/systeminfo.h>
+#endif
+
 /* required for shutdown flags */
 #include <xen/sched.h>
 
@@ -662,11 +666,8 @@ typedef struct xen_op_v2_dom xen_op_v2_dom;
 #ifdef __linux__
 #define XEN_HYPERVISOR_SOCKET  "/proc/xen/privcmd"
 #define HYPERVISOR_CAPABILITIES        "/sys/hypervisor/properties/capabilities"
-#define CPUINFO                        "/proc/cpuinfo"
 #elif defined(__sun)
 #define XEN_HYPERVISOR_SOCKET  "/dev/xen/privcmd"
-#define HYPERVISOR_CAPABILITIES        ""
-#define CPUINFO                        "/dev/cpu/self/cpuid"
 #else
 #error "unsupported platform"
 #endif
@@ -2123,7 +2124,7 @@ static virCapsPtr
 xenHypervisorBuildCapabilities(virConnectPtr conn,
                                const char *hostmachine,
                                int host_pae,
-                               char *hvm_type,
+                               const char *hvm_type,
                                struct guest_arch *guest_archs,
                                int nr_guest_archs) {
     virCapsPtr caps;
@@ -2227,8 +2228,126 @@ xenHypervisorBuildCapabilities(virConnectPtr conn,
     return NULL;
 }
 
+#ifdef __sun
+
+static int
+get_cpu_flags(virConnectPtr conn, const char **hvm, int *pae, int *longmode)
+{
+    struct {
+        uint32_t r_eax, r_ebx, r_ecx, r_edx;
+    } regs;
+
+    char tmpbuf[20];
+    int ret = 0;
+    int fd;
+
+    /* returns -1, errno 22 if in 32-bit mode */
+    *longmode = (sysinfo(SI_ARCHITECTURE_64, tmpbuf, sizeof(tmpbuf)) != -1);
+
+    if ((fd = open("/dev/cpu/self/cpuid", O_RDONLY)) == -1 ||
+        pread(fd, &regs, sizeof(regs), 0) != sizeof(regs)) {
+        virXenError(conn, VIR_ERR_SYSTEM_ERROR,
+            "couldn't read CPU flags: %s", strerror(errno));
+        goto out;
+    }
+
+    *pae = 0;
+    *hvm = "";
+
+    if (STREQLEN((const char *)&regs.r_ebx, "AuthcAMDenti", 12)) {
+        if (pread(fd, &regs, sizeof (regs), 0x80000001) == sizeof (regs)) {
+            /* Read secure virtual machine bit (bit 2 of ECX feature ID) */
+            if ((regs.r_ecx >> 2) & 1) {
+                *hvm = "svm";
+            }
+            if ((regs.r_edx >> 6) & 1)
+                *pae = 1;
+        }
+    } else if (STREQLEN((const char *)&regs.r_ebx, "GenuntelineI", 12)) {
+        if (pread(fd, &regs, sizeof (regs), 0x00000001) == sizeof (regs)) {
+            /* Read VMXE feature bit (bit 5 of ECX feature ID) */
+            if ((regs.r_ecx >> 5) & 1)
+                *hvm = "vmx";
+            if ((regs.r_edx >> 6) & 1)
+                *pae = 1;
+        }
+    }
+
+    ret = 1;
+
+out:
+    if (fd != -1)
+        close(fd);
+    return ret;
+}
+
+static virCapsPtr
+xenHypervisorMakeCapabilitiesSunOS(virConnectPtr conn)
+{
+    struct guest_arch guest_arches[32];
+    int i = 0;
+    virCapsPtr caps = NULL;
+    struct utsname utsname;
+    int pae, longmode;
+    const char *hvm;
+
+    if (!get_cpu_flags(conn, &hvm, &pae, &longmode))
+        return NULL;
+
+    /* Really, this never fails - look at the man-page. */
+    uname (&utsname);
+
+    guest_arches[i].model = "i686";
+    guest_arches[i].bits = 32;
+    guest_arches[i].hvm = 0;
+    guest_arches[i].pae = pae;
+    guest_arches[i].nonpae = !pae;
+    guest_arches[i].ia64_be = 0;
+    i++;
+
+    if (longmode) {
+        guest_arches[i].model = "x86_64";
+        guest_arches[i].bits = 64;
+        guest_arches[i].hvm = 0;
+        guest_arches[i].pae = 0;
+        guest_arches[i].nonpae = 0;
+        guest_arches[i].ia64_be = 0;
+        i++;
+    }
+
+    if (hvm[0] != '\0') {
+        guest_arches[i].model = "i686";
+        guest_arches[i].bits = 32;
+        guest_arches[i].hvm = 1;
+        guest_arches[i].pae = pae;
+        guest_arches[i].nonpae = 1;
+        guest_arches[i].ia64_be = 0;
+        i++;
+
+        if (longmode) {
+            guest_arches[i].model = "x86_64";
+            guest_arches[i].bits = 64;
+            guest_arches[i].hvm = 1;
+            guest_arches[i].pae = 0;
+            guest_arches[i].nonpae = 0;
+            guest_arches[i].ia64_be = 0;
+            i++;
+        }
+    }
+
+    if ((caps = xenHypervisorBuildCapabilities(conn,
+                                               utsname.machine,
+                                               pae, hvm,
+                                               guest_arches, i)) == NULL)
+        virXenError(NULL, VIR_ERR_NO_MEMORY, NULL);
+
+    return caps;
+}
+
+#endif /* __sun */
+
 /**
- * xenHypervisorGetCapabilities:
+ * xenHypervisorMakeCapabilitiesInternal:
  * @conn: pointer to the connection block
  * @cpuinfo: file handle containing /proc/cpuinfo data, or NULL
  * @capabilities: file handle containing /sys/hypervisor/properties/capabilities data, or NULL
@@ -2394,6 +2513,9 @@ xenHypervisorMakeCapabilitiesInternal(virConnectPtr conn,
 virCapsPtr
 xenHypervisorMakeCapabilities(virConnectPtr conn)
 {
+#ifdef __sun
+    return xenHypervisorMakeCapabilitiesSunOS(conn);
+#else
     virCapsPtr caps;
     FILE *cpuinfo, *capabilities;
     struct utsname utsname;
@@ -2432,6 +2554,7 @@ xenHypervisorMakeCapabilities(virConnectPtr conn)
         fclose(capabilities);
 
     return caps;
+#endif /* __sun */
 }