diff --git a/ChangeLog b/ChangeLog
index abb1442f98..33aa391680 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Fri Aug 10 14:25:00 EST 2007 Daniel P. Berrange <berrange@redhat.com>
+
+	* src/xen_internal.c, src/xen_internal.h, src/xen_unified.c:
+	Add impls of the DomainGetOSType, DomainLookupByID and
+	DomainLookupByName drivers using the HV for speed
+	* src/xs_internal.c, src/xs_internal.h: Add helper method to
+	lookup a domain name based on its ID
+
 Thu Aug  9 14:27:00 EST 2007 Daniel P. Berrange <berrange@redhat.com>
 
 	* src/libvirt.c, src/openvz_conf.c, src/qemu_conf.c,
diff --git a/src/xen_internal.c b/src/xen_internal.c
index 17df827faa..638e340d45 100644
--- a/src/xen_internal.c
+++ b/src/xen_internal.c
@@ -27,6 +27,7 @@
 #include <regex.h>
 #include <errno.h>
 #include <sys/utsname.h>
+#include "xs_internal.h"
 
 /* required for dom0_getdomaininfo_t */
 #include <xen/dom0_ops.h>
@@ -229,6 +230,13 @@ typedef union xen_getschedulerid xen_getschedulerid;
       domlist.v2[n].domain :                        \
       domlist.v2d5[n].domain))
 
+#define XEN_GETDOMAININFOLIST_UUID(domlist, n)      \
+    (hypervisor_version < 2 ?                       \
+     domlist.v0[n].handle :                         \
+     (dom_interface_version < 5 ?                   \
+      domlist.v2[n].handle :                        \
+      domlist.v2d5[n].handle))
+
 #define XEN_GETDOMAININFOLIST_DATA(domlist)        \
     (hypervisor_version < 2 ?                      \
      (void*)(domlist->v0) :                        \
@@ -299,6 +307,13 @@ typedef union xen_getschedulerid xen_getschedulerid;
       dominfo.v2.max_pages :                    \
       dominfo.v2d5.max_pages))
 
+#define XEN_GETDOMAININFO_UUID(dominfo)         \
+    (hypervisor_version < 2 ?                   \
+     dominfo.v0.handle :                        \
+     (dom_interface_version < 5 ?               \
+      dominfo.v2.handle :                       \
+      dominfo.v2d5.handle))
+
 
 
 struct xen_v0_getdomaininfolistop {
@@ -626,7 +641,7 @@ struct xenUnifiedDriver xenHypervisorDriver = {
     NULL, /* domainShutdown */
     NULL, /* domainReboot */
     xenHypervisorDestroyDomain, /* domainDestroy */
-    NULL, /* domainGetOSType */
+    xenHypervisorDomainGetOSType, /* domainGetOSType */
     xenHypervisorGetMaxMemory, /* domainGetMaxMemory */
     xenHypervisorSetMaxMemory, /* domainSetMaxMemory */
     NULL, /* domainSetMemory */
@@ -2437,6 +2452,136 @@ xenHypervisorListDomains(virConnectPtr conn, int *ids, int maxids)
     return (nbids);
 }
 
+
+#ifndef PROXY
+char *
+xenHypervisorDomainGetOSType (virDomainPtr dom)
+{
+    xenUnifiedPrivatePtr priv;
+    xen_getdomaininfo dominfo;
+
+    priv = (xenUnifiedPrivatePtr) dom->conn->privateData;
+    if (priv->handle < 0)
+        return (NULL);
+
+    /* HV's earlier than 3.1.0 don't include the HVM flags in guests status*/
+    if (hypervisor_version < 2 ||
+        dom_interface_version < 4)
+        return (NULL);
+
+    XEN_GETDOMAININFO_CLEAR(dominfo);
+
+    if (virXen_getdomaininfo(priv->handle, dom->id, &dominfo) < 0)
+        return (NULL);
+
+    if (XEN_GETDOMAININFO_DOMAIN(dominfo) != dom->id)
+        return (NULL);
+
+    if (XEN_GETDOMAININFO_FLAGS(dominfo) & DOMFLAGS_HVM)
+        return strdup("hvm");
+    return strdup("linux");
+}
+
+virDomainPtr
+xenHypervisorLookupDomainByID(virConnectPtr conn,
+                              int id)
+{
+    xenUnifiedPrivatePtr priv;
+    xen_getdomaininfo dominfo;
+    virDomainPtr ret;
+    char *name;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->handle < 0)
+        return (NULL);
+
+    XEN_GETDOMAININFO_CLEAR(dominfo);
+
+    if (virXen_getdomaininfo(priv->handle, id, &dominfo) < 0)
+        return (NULL);
+
+    if (XEN_GETDOMAININFO_DOMAIN(dominfo) != id)
+        return (NULL);
+
+
+    if (!(name = xenStoreDomainGetName(conn, id)))
+        return (NULL);
+
+    ret = virGetDomain(conn, name, XEN_GETDOMAININFO_UUID(dominfo));
+    if (ret)
+        ret->id = id;
+    free(name);
+    return ret;
+}
+
+
+virDomainPtr
+xenHypervisorLookupDomainByUUID(virConnectPtr conn,
+                                const unsigned char *uuid)
+{
+    xen_getdomaininfolist dominfos;
+    xenUnifiedPrivatePtr priv;
+    virDomainPtr ret;
+    char *name;
+    int maxids = 100, nids, i, id;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->handle < 0)
+        return (NULL);
+
+ retry:
+    if (!(XEN_GETDOMAININFOLIST_ALLOC(dominfos, maxids))) {
+        virXenError(VIR_ERR_NO_MEMORY, "allocating %d domain info",
+                    maxids);
+        return(NULL);
+    }
+
+    XEN_GETDOMAININFOLIST_CLEAR(dominfos, maxids);
+
+    nids = virXen_getdomaininfolist(priv->handle, 0, maxids, &dominfos);
+
+    if (nids < 0) {
+        XEN_GETDOMAININFOLIST_FREE(dominfos);
+        return (NULL);
+    }
+
+    /* Can't possibly have more than 65,000 concurrent guests
+     * so limit how many times we try, to avoid increasing
+     * without bound & thus allocating all of system memory !
+     * XXX I'll regret this comment in a few years time ;-)
+     */
+    if (nids == maxids) {
+        XEN_GETDOMAININFOLIST_FREE(dominfos);
+        if (maxids < 65000) {
+            maxids *= 2;
+            goto retry;
+        }
+        return (NULL);
+    }
+
+    id = -1;
+    for (i = 0 ; i < nids ; i++) {
+        if (memcmp(XEN_GETDOMAININFOLIST_UUID(dominfos, i), uuid, VIR_UUID_BUFLEN) == 0) {
+            id = XEN_GETDOMAININFOLIST_DOMAIN(dominfos, i);
+            break;
+        }
+    }
+    XEN_GETDOMAININFOLIST_FREE(dominfos);
+
+    if (id == -1)
+        return (NULL);
+
+    if (!(name = xenStoreDomainGetName(conn, id)))
+        return (NULL);
+
+    ret = virGetDomain(conn, name, uuid);
+    if (ret)
+        ret->id = id;
+    free(name);
+    return ret;
+}
+#endif
+
 /**
  * xenHypervisorGetMaxVcpus:
  *
diff --git a/src/xen_internal.h b/src/xen_internal.h
index 65a7ace8ec..6d5c1cbce4 100644
--- a/src/xen_internal.h
+++ b/src/xen_internal.h
@@ -20,6 +20,15 @@ int	xenHypervisorInit		(void);
 
 /* The following calls are made directly by the Xen proxy: */
 
+virDomainPtr
+        xenHypervisorLookupDomainByID   (virConnectPtr conn,
+					 int id);
+virDomainPtr
+xenHypervisorLookupDomainByUUID(virConnectPtr conn,
+                                const unsigned char *uuid);
+char *
+        xenHypervisorDomainGetOSType (virDomainPtr dom);
+
 int	xenHypervisorOpen		(virConnectPtr conn,
 					 const char *name,
 					 int flags);
diff --git a/src/xen_unified.c b/src/xen_unified.c
index 69bc1e6fb2..5d9bb9418e 100644
--- a/src/xen_unified.c
+++ b/src/xen_unified.c
@@ -377,6 +377,13 @@ xenUnifiedDomainLookupByID (virConnectPtr conn, int id)
      */
     virConnResetLastError (conn);
 
+    /* Try hypervisor/xenstore combo. */
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
+        ret = xenHypervisorLookupDomainByID (conn, id);
+        if (ret || conn->err.code != VIR_ERR_OK)
+            return ret;
+    }
+
     /* Try proxy. */
     if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
         ret = xenProxyLookupByID (conn, id);
@@ -408,6 +415,13 @@ xenUnifiedDomainLookupByUUID (virConnectPtr conn,
      */
     virConnResetLastError (conn);
 
+    /* Try hypervisor/xenstore combo. */
+    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
+        ret = xenHypervisorLookupDomainByUUID (conn, uuid);
+        if (ret || conn->err.code != VIR_ERR_OK)
+            return ret;
+    }
+
     /* Try proxy. */
     if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
         ret = xenProxyLookupByUUID (conn, uuid);
diff --git a/src/xs_internal.c b/src/xs_internal.c
index 4569e54688..ef7248fc61 100644
--- a/src/xs_internal.c
+++ b/src/xs_internal.c
@@ -875,6 +875,22 @@ xenStoreDomainGetNetworkID(virConnectPtr conn, int id, const char *mac) {
     return(ret);
 }
 
+char *xenStoreDomainGetName(virConnectPtr conn,
+                            int id) {
+    char prop[200];
+    xenUnifiedPrivatePtr priv;
+    unsigned int len;
+
+    priv = (xenUnifiedPrivatePtr) conn->privateData;
+    if (priv->xshandle == NULL)
+        return(NULL);
+
+    snprintf(prop, 199, "/local/domain/%d/name", id);
+    prop[199] = 0;
+    return xs_read(priv->xshandle, 0, prop, &len);
+}
+
+
 #endif /* WITH_XEN */
 /*
  * Local variables:
diff --git a/src/xs_internal.h b/src/xs_internal.h
index a5001e5612..cd2f0ed55e 100644
--- a/src/xs_internal.h
+++ b/src/xs_internal.h
@@ -15,6 +15,8 @@
 extern "C" {
 #endif
 
+#include "internal.h"
+
 extern struct xenUnifiedDriver xenStoreDriver;
 int xenStoreInit (void);
 
@@ -48,6 +50,8 @@ char *		xenStoreDomainGetOSTypeID(virConnectPtr conn,
 char *		xenStoreDomainGetNetworkID(virConnectPtr conn,
 					 int id,
 					 const char *mac);
+char *          xenStoreDomainGetName(virConnectPtr conn,
+				      int id);
 
 #ifdef __cplusplus
 }