]> xenbits.xensource.com Git - libvirt.git/commitdiff
* include/libvirt/libvirt.h include/libvirt/libvirt.h.in
authorDaniel Veillard <veillard@redhat.com>
Fri, 4 Aug 2006 10:41:05 +0000 (10:41 +0000)
committerDaniel Veillard <veillard@redhat.com>
Fri, 4 Aug 2006 10:41:05 +0000 (10:41 +0000)
  src/libvirt.c src/libvirt_sym.version src/xen_internal.c
  src/xen_internal.h src/xend_internal.c src/xend_internal.h:
  applied patch from Michel Ponceau and Philippe Berthault for
  virtual CPU and affinity support plus a bit of cleanup.
Daniel

ChangeLog
include/libvirt/libvirt.h
include/libvirt/libvirt.h.in
src/libvirt.c
src/libvirt_sym.version
src/xen_internal.c
src/xen_internal.h
src/xend_internal.c
src/xend_internal.h

index 0dfb41d112b4aacea753f38944e5a17899d0cab8..aa432be5070d4c0cb8b603aab6259f23b402e33f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Fri Aug  4 11:49:44 CEST 2006 Daniel Veillard <veillard@redhat.com>
+
+       * include/libvirt/libvirt.h include/libvirt/libvirt.h.in
+         src/libvirt.c src/libvirt_sym.version src/xen_internal.c
+         src/xen_internal.h src/xend_internal.c src/xend_internal.h:
+         applied patch from Michel Ponceau and Philippe Berthault for
+         virtual CPU and affinity support plus a bit of cleanup.
+
 Tue Aug  1 16:22:52 CEST 2006 Daniel Veillard <veillard@redhat.com>
 
        * libvirt.spec.in: xen is now built for ia64, c.f. RH#199685
index 523bb73011b902f887fc8c7156e653f7cd97baaa..2db8beba03ba7424f100a172198464e048b602d1 100644 (file)
@@ -290,6 +290,107 @@ int                       virConnectListDefinedDomains(virConnectPtr conn,
                                                 int maxnames);
 int                    virDomainCreate         (virDomainPtr domain);
 
+/**
+ * virVcpuInfo: structure for information about a virtual CPU in a domain.
+ */
+
+typedef enum {
+    VIR_VCPU_OFFLINE   = 0,    /* the virtual CPU is offline */
+    VIR_VCPU_RUNNING   = 1,    /* the virtual CPU is running */
+    VIR_VCPU_BLOCKED   = 2,    /* the virtual CPU is blocked on resource */
+} virVcpuState;
+
+typedef struct _virVcpuInfo virVcpuInfo;
+struct _virVcpuInfo {
+    unsigned int number;       /* virtual CPU number */
+    int state;                 /* value from virVcpuState */
+    unsigned long long cpuTime; /* CPU time used, in nanoseconds */
+    int cpu;                   /* real CPU number, or -1 if offline */
+};
+typedef virVcpuInfo *virVcpuInfoPtr;
+
+int                    virDomainSetVcpus       (virDomainPtr domain,
+                                                unsigned int nvcpus);
+
+int                    virDomainPinVcpu        (virDomainPtr domain,
+                                                unsigned int vcpu,
+                                                unsigned char *cpumap,
+                                                int maplen);
+
+/**
+ * VIR_USE_CPU:
+ * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN/OUT)
+ * @cpu: the physical CPU number
+ *
+ * This macro is to be used in conjonction with virDomainPinVcpu() API.
+ * USE_CPU macro set the bit (CPU usable) of the related cpu in cpumap.
+ */
+
+#define VIR_USE_CPU(cpumap,cpu)        (cpumap[(cpu)/8] |= (1<<((cpu)%8)))
+
+/**
+ * VIR_UNUSE_CPU:
+ * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN/OUT)
+ * @cpu: the physical CPU number
+ *
+ * This macro is to be used in conjonction with virDomainPinVcpu() API.
+ * USE_CPU macro reset the bit (CPU not usable) of the related cpu in cpumap.
+ */
+
+#define VIR_UNUSE_CPU(cpumap,cpu)      (cpumap[(cpu)/8] &= ~(1<<((cpu)%8)))
+
+int                    virDomainGetVcpus       (virDomainPtr domain,
+                                                virVcpuInfoPtr info,
+                                                int maxinfo,
+                                                unsigned char *cpumaps,
+                                                int maplen);
+
+/**
+ * VIR_CPU_USABLE:
+ * @cpumaps: pointer to an array of cpumap (in 8-bit bytes) (IN)
+ * @maplen: the length (in bytes) of one cpumap
+ * @vcpu: the virtual CPU number
+ * @cpu: the physical CPU number
+ *
+ * This macro is to be used in conjonction with virDomainGetVcpus() API.
+ * VIR_CPU_USABLE macro returns a non zero value (true) if the cpu
+ * is usable by the vcpu, and 0 otherwise.
+ */
+
+#define VIR_CPU_USABLE(cpumaps,maplen,vcpu,cpu) \
+       (cpumaps[((vcpu)*(maplen))+((cpu)/8)] & (1<<((cpu)%8)))
+
+/**
+ * VIR_COPY_CPUMAP:
+ * @cpumaps: pointer to an array of cpumap (in 8-bit bytes) (IN)
+ * @maplen: the length (in bytes) of one cpumap
+ * @vcpu: the virtual CPU number
+ * @cpumap: pointer to a cpumap (in 8-bit bytes) (OUT)
+ *     This cpumap must be previously allocated by the caller
+ *      (ie: malloc(maplen))
+ *
+ * This macro is to be used in conjonction with virDomainGetVcpus() and
+ * virDomainPinVcpu() APIs. VIR_COPY_CPUMAP macro extract the cpumap of
+ * the specified vcpu from cpumaps array and copy it into cpumap to be used
+ * later by virDomainPinVcpu() API.
+ */
+#define VIR_COPY_CPUMAP(cpumaps,maplen,vcpu,cpumap) \
+       memcpy(cpumap, &(cpumaps[(vcpu)*(maplen)]), (maplen))
+
+
+/**
+ * VIR_GET_CPUMAP:
+ * @cpumaps: pointer to an array of cpumap (in 8-bit bytes) (IN)
+ * @maplen: the length (in bytes) of one cpumap
+ * @vcpu: the virtual CPU number
+ *
+ * This macro is to be used in conjonction with virDomainGetVcpus() and
+ * virDomainPinVcpu() APIs. VIR_GET_CPUMAP macro returns a pointer to the
+ * cpumap of the specified vcpu from cpumaps array.
+ */
+#define VIR_GET_CPUMAP(cpumaps,maplen,vcpu)    &(cpumaps[(vcpu)*(maplen)])
+
+
 #ifdef __cplusplus
 }
 #endif
index 2668eaafcd55a770c70cf5308b2a9c9f4be7c27f..3f8a504ca7c750a1bcc8208416cb83df3641d814 100644 (file)
@@ -290,6 +290,107 @@ int                       virConnectListDefinedDomains(virConnectPtr conn,
                                                 int maxnames);
 int                    virDomainCreate         (virDomainPtr domain);
 
+/**
+ * virVcpuInfo: structure for information about a virtual CPU in a domain.
+ */
+
+typedef enum {
+    VIR_VCPU_OFFLINE   = 0,    /* the virtual CPU is offline */
+    VIR_VCPU_RUNNING   = 1,    /* the virtual CPU is running */
+    VIR_VCPU_BLOCKED   = 2,    /* the virtual CPU is blocked on resource */
+} virVcpuState;
+
+typedef struct _virVcpuInfo virVcpuInfo;
+struct _virVcpuInfo {
+    unsigned int number;       /* virtual CPU number */
+    int state;                 /* value from virVcpuState */
+    unsigned long long cpuTime; /* CPU time used, in nanoseconds */
+    int cpu;                   /* real CPU number, or -1 if offline */
+};
+typedef virVcpuInfo *virVcpuInfoPtr;
+
+int                    virDomainSetVcpus       (virDomainPtr domain,
+                                                unsigned int nvcpus);
+
+int                    virDomainPinVcpu        (virDomainPtr domain,
+                                                unsigned int vcpu,
+                                                unsigned char *cpumap,
+                                                int maplen);
+
+/**
+ * VIR_USE_CPU:
+ * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN/OUT)
+ * @cpu: the physical CPU number
+ *
+ * This macro is to be used in conjonction with virDomainPinVcpu() API.
+ * USE_CPU macro set the bit (CPU usable) of the related cpu in cpumap.
+ */
+
+#define VIR_USE_CPU(cpumap,cpu)        (cpumap[(cpu)/8] |= (1<<((cpu)%8)))
+
+/**
+ * VIR_UNUSE_CPU:
+ * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN/OUT)
+ * @cpu: the physical CPU number
+ *
+ * This macro is to be used in conjonction with virDomainPinVcpu() API.
+ * USE_CPU macro reset the bit (CPU not usable) of the related cpu in cpumap.
+ */
+
+#define VIR_UNUSE_CPU(cpumap,cpu)      (cpumap[(cpu)/8] &= ~(1<<((cpu)%8)))
+
+int                    virDomainGetVcpus       (virDomainPtr domain,
+                                                virVcpuInfoPtr info,
+                                                int maxinfo,
+                                                unsigned char *cpumaps,
+                                                int maplen);
+
+/**
+ * VIR_CPU_USABLE:
+ * @cpumaps: pointer to an array of cpumap (in 8-bit bytes) (IN)
+ * @maplen: the length (in bytes) of one cpumap
+ * @vcpu: the virtual CPU number
+ * @cpu: the physical CPU number
+ *
+ * This macro is to be used in conjonction with virDomainGetVcpus() API.
+ * VIR_CPU_USABLE macro returns a non zero value (true) if the cpu
+ * is usable by the vcpu, and 0 otherwise.
+ */
+
+#define VIR_CPU_USABLE(cpumaps,maplen,vcpu,cpu) \
+       (cpumaps[((vcpu)*(maplen))+((cpu)/8)] & (1<<((cpu)%8)))
+
+/**
+ * VIR_COPY_CPUMAP:
+ * @cpumaps: pointer to an array of cpumap (in 8-bit bytes) (IN)
+ * @maplen: the length (in bytes) of one cpumap
+ * @vcpu: the virtual CPU number
+ * @cpumap: pointer to a cpumap (in 8-bit bytes) (OUT)
+ *     This cpumap must be previously allocated by the caller
+ *      (ie: malloc(maplen))
+ *
+ * This macro is to be used in conjonction with virDomainGetVcpus() and
+ * virDomainPinVcpu() APIs. VIR_COPY_CPUMAP macro extract the cpumap of
+ * the specified vcpu from cpumaps array and copy it into cpumap to be used
+ * later by virDomainPinVcpu() API.
+ */
+#define VIR_COPY_CPUMAP(cpumaps,maplen,vcpu,cpumap) \
+       memcpy(cpumap, &(cpumaps[(vcpu)*(maplen)]), (maplen))
+
+
+/**
+ * VIR_GET_CPUMAP:
+ * @cpumaps: pointer to an array of cpumap (in 8-bit bytes) (IN)
+ * @maplen: the length (in bytes) of one cpumap
+ * @vcpu: the virtual CPU number
+ *
+ * This macro is to be used in conjonction with virDomainGetVcpus() and
+ * virDomainPinVcpu() APIs. VIR_GET_CPUMAP macro returns a pointer to the
+ * cpumap of the specified vcpu from cpumaps array.
+ */
+#define VIR_GET_CPUMAP(cpumaps,maplen,vcpu)    &(cpumaps[(vcpu)*(maplen)])
+
+
 #ifdef __cplusplus
 }
 #endif
index f5734d2f78b8c6186d76d66c440b960fb7f93439..70fcf0a7bccc86a114ee9975ca97d886bfa7ffde 100644 (file)
@@ -1649,3 +1649,132 @@ virDomainCreate(virDomainPtr domain) {
     return(-1);
 }
 
+/**
+ * virDomainSetVcpus:
+ * @domain: pointer to domain object, or NULL for Domain0
+ * @nvcpus: the new number of virtual CPUs for this domain
+ *
+ * Dynamically change the number of virtual CPUs used by the domain.
+ * Note that this call may fail if the underlying virtualization hypervisor
+ * does not support it or if growing the number is arbitrary limited.
+ * This function requires priviledged access to the hypervisor.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+
+int
+virDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus)
+{
+    if (domain == NULL) {
+        TODO
+       return (-1);
+    }
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO)
+        return (-1);
+    if (nvcpus < 1) {
+        virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+    /* TODO: access though the driver API not directly */
+
+#if 0
+    if (xenHypervisorSetVcpus(domain, nvcpus) == 0)
+        return 0;
+#endif
+    return xenDaemonDomainSetVcpus(domain, nvcpus);
+}
+
+/**
+ * virDomainPinVcpu:
+ * @domain: pointer to domain object, or NULL for Domain0
+ * @vcpu: virtual CPU number
+ * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN)
+ *     Each bit set to 1 means that corresponding CPU is usable.
+ *     Bytes are stored in little-endian order: CPU0-7, 8-15...
+ *     In each byte, lowest CPU number is least significant bit.
+ * @maplen: number of bytes in cpumap, from 1 up to size of CPU map in
+ *     underlying virtualization system (Xen...).
+ *     If maplen < size, missing bytes are set to zero.
+ *     If maplen > size, failure code is returned.
+ * 
+ * Dynamically change the real CPUs which can be allocated to a virtual CPU.
+ * This function requires priviledged access to the hypervisor.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+int
+virDomainPinVcpu(virDomainPtr domain, unsigned int vcpu,
+                 unsigned char *cpumap, int maplen)
+{
+    if (domain == NULL) {
+        TODO
+       return (-1);
+    }
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if (domain->conn->flags & VIR_CONNECT_RO)
+        return (-1);
+    if ((vcpu < 1) || (cpumap == NULL) || (maplen < 1)) {
+        virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+    /* TODO: access though the driver API not directly */
+    if (xenHypervisorPinVcpu(domain, vcpu, cpumap, maplen) == 0)
+        return 0;
+    return (-1); //xenDaemonDomainPinVcpu(domain, vcpu, cpumap, maplen);
+}
+
+/**
+ * virDomainGetVcpus:
+ * @domain: pointer to domain object, or NULL for Domain0
+ * @info: pointer to an array of virVcpuInfo structures (OUT)
+ * @maxinfo: number of structures in info array
+ * @cpumaps: pointer to an bit map of real CPUs for all vcpus of this
+ *      domain (in 8-bit bytes) (OUT)
+ *     If cpumaps is NULL, then no cupmap information is returned by the API.
+ *     It's assumed there is <maxinfo> cpumap in cpumaps array.
+ *     The memory allocated to cpumaps must be (maxinfo * maplen) bytes
+ *     (ie: calloc(maxinfo, maplen)).
+ *     One cpumap inside cpumaps has the format described in
+ *      virDomainPinVcpu() API.
+ * @maplen: number of bytes in one cpumap, from 1 up to size of CPU map in
+ *     underlying virtualization system (Xen...).
+ * 
+ * Extract information about virtual CPUs of domain, store it in info array
+ * and also in cpumaps if this pointer is'nt NULL.
+ *
+ * Returns the number of info filled in case of success, -1 in case of failure.
+ */
+int
+virDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
+                 unsigned char *cpumaps, int maplen)
+{
+    int ret;
+
+    if (domain == NULL) {
+        TODO
+       return (-1);
+    }
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (-1);
+    }
+    if ((info == NULL) || (maxinfo < 1)) {
+        virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+    if (cpumaps != NULL && maplen < 1) {
+        virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
+        return (-1);
+    }
+    /* TODO: access though the driver API not directly */
+    ret = xenHypervisorGetVcpus(domain, info, maxinfo, cpumaps, maplen);
+    if (ret != -1) return ret;
+    return xenDaemonDomainGetVcpus(domain, info, maxinfo, cpumaps, maplen);
+}
index 0fe40693bcff51fe747b6d8ede30a9e98a78d9b7..e29ce78b9d8d0b624014eb5e4fede21d11eb04b5 100644 (file)
@@ -47,5 +47,9 @@
        virConnResetLastError;
        virDefaultErrorFunc;
        virNodeGetInfo;
+
+       virDomainSetVcpus;
+       virDomainPinVcpu;
+       virDomainGetVcpus;
     local: *;
 };
index d0ca433a9478db9f65fa0ee653c54078d416e5e5..8887abbe945e5cc2c810006461a56e12ddd38af6 100644 (file)
@@ -18,7 +18,7 @@
 #include <fcntl.h>
 #include <sys/mman.h>
 #include <sys/ioctl.h>
-
+#include <limits.h>
 #include <stdint.h>
 
 /* required for dom0_getdomaininfo_t */
@@ -845,3 +845,136 @@ xenHypervisorCheckID(virConnectPtr conn, int id)
     return (0);
 }
 
+/**
+ * xenHypervisorSetVcpus:
+ * @domain: pointer to domain object
+ * @nvcpus: the new number of virtual CPUs for this domain
+ *
+ * Dynamically change the number of virtual CPUs used by the domain.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+
+int
+xenHypervisorSetVcpus(virDomainPtr domain, unsigned int nvcpus)
+{
+    dom0_op_t op;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->conn->handle < 0)
+     || (nvcpus < 1))
+        return (-1);
+    op.cmd = DOM0_MAX_VCPUS;
+    op.u.max_vcpus.domain = (domid_t) domain->handle;
+    op.u.max_vcpus.max = nvcpus;
+    if (xenHypervisorDoOp(domain->conn->handle, &op) < 0)
+        return (-1);
+    return 0;
+}
+
+/**
+ * xenHypervisorPinVcpu:
+ * @domain: pointer to domain object
+ * @vcpu: virtual CPU number
+ * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes)
+ * @maplen: length of cpumap in bytes
+ * 
+ * Dynamically change the real CPUs which can be allocated to a virtual CPU.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+
+int
+xenHypervisorPinVcpu(virDomainPtr domain, unsigned int vcpu,
+                     unsigned char *cpumap, int maplen)
+{
+    dom0_op_t op;
+    uint64_t *pm = (uint64_t *)&op.u.setvcpuaffinity.cpumap; 
+    int j;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->conn->handle < 0)
+     || (cpumap == NULL) || (maplen < 1) || (maplen > (int)sizeof(cpumap_t))
+     || (sizeof(cpumap_t) & 7))
+        return (-1);
+    op.cmd = DOM0_SETVCPUAFFINITY;
+    op.u.setvcpuaffinity.domain = (domid_t) domain->handle;
+    op.u.setvcpuaffinity.vcpu = vcpu;
+    memset(pm, 0, sizeof(cpumap_t));
+    for (j = 0; j < maplen; j++)
+        *(pm + (j / 8)) |= cpumap[j] << (8 * (j & 7));
+    if (xenHypervisorDoOp(domain->conn->handle, &op) < 0)
+        return (-1);
+    return 0;
+}
+
+/**
+ * virDomainGetVcpus:
+ * @domain: pointer to domain object, or NULL for Domain0
+ * @info: pointer to an array of virVcpuInfo structures (OUT)
+ * @maxinfo: number of structures in info array
+ * @cpumaps: pointer to an bit map of real CPUs for all vcpus of this domain (in 8-bit bytes) (OUT)
+ *     If cpumaps is NULL, then no cupmap information is returned by the API.
+ *     It's assumed there is <maxinfo> cpumap in cpumaps array.
+ *     The memory allocated to cpumaps must be (maxinfo * maplen) bytes
+ *     (ie: calloc(maxinfo, maplen)).
+ *     One cpumap inside cpumaps has the format described in virDomainPinVcpu() API.
+ * @maplen: number of bytes in one cpumap, from 1 up to size of CPU map in
+ *     underlying virtualization system (Xen...).
+ * 
+ * Extract information about virtual CPUs of domain, store it in info array
+ * and also in cpumaps if this pointer is'nt NULL.
+ *
+ * Returns the number of info filled in case of success, -1 in case of failure.
+ */
+int
+xenHypervisorGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
+                     unsigned char *cpumaps, int maplen)
+{
+    dom0_op_t op;
+    uint64_t *pm = (uint64_t *)&op.u.getvcpuinfo.cpumap; 
+    virVcpuInfoPtr ipt;
+    int nbinfo, mapl, i;
+    unsigned char *cpumap;
+    int vcpu, cpu;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->conn->handle < 0)
+     || (info == NULL) || (maxinfo < 1)
+     || (sizeof(cpumap_t) & 7))
+        return (-1);
+    if (cpumaps != NULL && maplen < 1)
+       return -1;
+
+    /* first get the number of virtual CPUs in this domain */
+    op.cmd = DOM0_GETDOMAININFO;
+    op.u.getdomaininfo.domain = (domid_t) domain->handle;
+    if (xenHypervisorDoOp(domain->conn->handle, &op) < 0)
+        return (-1);
+    nbinfo = (int)op.u.getdomaininfo.max_vcpu_id + 1;
+    if (nbinfo > maxinfo) nbinfo = maxinfo;
+
+    if (cpumaps != NULL)
+       memset(cpumaps, 0, maxinfo * maplen);
+
+    op.cmd = DOM0_GETVCPUINFO;
+    for (i=0, ipt=info; i < nbinfo; i++, ipt++) {
+        vcpu = op.u.getvcpuinfo.vcpu = i;
+        if (xenHypervisorDoOp(domain->conn->handle, &op) < 0)
+            return (-1);
+        ipt->number = i;
+        if (op.u.getvcpuinfo.online) {
+            if (op.u.getvcpuinfo.running) ipt->state = VIR_VCPU_RUNNING;
+            if (op.u.getvcpuinfo.blocked) ipt->state = VIR_VCPU_BLOCKED;
+        }
+        else ipt->state = VIR_VCPU_OFFLINE;
+        ipt->cpuTime = op.u.getvcpuinfo.cpu_time;
+        ipt->cpu = op.u.getvcpuinfo.online ? (int)op.u.getvcpuinfo.cpu : -1;
+       if (cpumaps != NULL && vcpu >= 0 && vcpu < maxinfo) {
+           cpumap = (unsigned char *)VIR_GET_CPUMAP(cpumaps, maplen, vcpu);
+           mapl = (maplen > (int)sizeof(cpumap_t)) ? (int)sizeof(cpumap_t) : maplen;
+            for (cpu = 0; cpu < (mapl * CHAR_BIT); cpu++) {
+               if (*pm & ((uint64_t)1<<cpu))
+                   VIR_USE_CPU(cpumap, cpu);
+           }
+       }
+    }
+    return nbinfo;
+}
index 24a210717f301d817853e1ef83618724c81277bc..125b5b1435bfb12e451cdecdb20f50d3fb2dc21a 100644 (file)
@@ -44,6 +44,18 @@ int  xenHypervisorSetMaxMemory       (virDomainPtr domain,
                                         unsigned long memory);
 int    xenHypervisorCheckID            (virConnectPtr conn,
                                         int id);
+int    xenHypervisorSetVcpus           (virDomainPtr domain,
+                                        unsigned int nvcpus);
+int    xenHypervisorPinVcpu            (virDomainPtr domain,
+                                        unsigned int vcpu,
+                                        unsigned char *cpumap,
+                                        int maplen);
+int    xenHypervisorGetVcpus           (virDomainPtr domain,
+                                        virVcpuInfoPtr info,
+                                        int maxinfo,
+                                        unsigned char *cpumaps,
+                                        int maplen);
+
 #ifdef __cplusplus
 }
 #endif
index 5798e4be74a4976ff9c3b1f8a3e5e74632f6bc16..ab5ed6d5b7a8bca42d0847a715efc3cae819091f 100644 (file)
@@ -1392,14 +1392,18 @@ xend_parse_sexp_desc_os(struct sexpr *node, virBufferPtr buf, int hvm)
         virBufferVSprintf(buf, "    <loader>%s</loader>\n", tmp);
         tmp = sexpr_node(node, "domain/image/hvm/boot");
         if ((tmp != NULL) && (tmp[0] != 0)) {
-           // FIXME:
-           // Figure out how to map the 'a', 'b', 'c' nonsense to a
-           // device.
+          /*
+            * FIXME:
+            * Figure out how to map the 'a', 'b', 'c' nonsense to a
+            * device.
+           */
            if (tmp[0] == 'a')
                virBufferAdd(buf, "    <boot dev='/dev/fd0'/>\n", 25 );
            else if (tmp[0] == 'c')
-              // Don't know what to put here.  Say the vm has been given 3
-              // disks - hda, hdb, hdc.  How does one identify the boot disk?
+          /*
+            * Don't know what to put here.  Say the vm has been given 3
+            * disks - hda, hdb, hdc.  How does one identify the boot disk?
+           */
                virBufferAdd(buf, "    <boot dev='hda'/>\n", 22 );
            else if (strcmp(tmp, "d") == 0)
                virBufferAdd(buf, "    <boot dev='/dev/cdrom'/>\n", 24 );
@@ -2434,6 +2438,158 @@ xenDaemonLookupByID(virConnectPtr conn, int id) {
     return (NULL);
 }
 
+/**
+ * xenDaemonDomainSetVcpus:
+ * @domain: pointer to domain object
+ * @nvcpus: the new number of virtual CPUs for this domain
+ *
+ * Dynamically change the number of virtual CPUs used by the domain.
+ *
+ * Returns 0 for success; -1 (with errno) on error
+ */
+int
+xenDaemonDomainSetVcpus(virDomainPtr domain, int vcpus)
+{
+    char buf[16];
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
+     || (vcpus < 1)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                    __FUNCTION__);
+        return (-1);
+    }
+    snprintf(buf, sizeof(buf), "%d", vcpus);
+    return(xend_op(domain->conn, domain->name, "op", "set_vcpus", "vcpus",
+                   buf, NULL));
+}
+
+/**
+ * xenDaemonDomainPinCpu:
+ * @domain: pointer to domain object
+ * @vcpu: virtual CPU number
+ * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes)
+ * @maplen: length of cpumap in bytes
+ * 
+ * Dynamically change the real CPUs which can be allocated to a virtual CPU.
+ *
+ * Returns 0 for success; -1 (with errno) on error
+ */
+int
+xenDaemonDomainPinVcpu(virDomainPtr domain, unsigned int vcpu,
+                     unsigned char *cpumap, int maplen)
+{
+    char buf[16], mapstr[sizeof(cpumap_t) * 64] = "[";
+    int i, j;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
+     || (cpumap == NULL) || (maplen < 1) || (maplen > (int)sizeof(cpumap_t))) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                    __FUNCTION__);
+        return (-1);
+    }
+
+    /* from bit map, build character string of mapped CPU numbers */
+    for (i = 0; i < maplen; i++) for (j = 0; j < 8; j++)
+     if (cpumap[i] & (1 << j)) {
+        sprintf(buf, "%d,", (8 * i) + j);
+        strcat(mapstr, buf);
+    }
+    mapstr[strlen(mapstr) - 1] = ']';
+    snprintf(buf, sizeof(buf), "%d", vcpu);
+    return(xend_op(domain->conn, domain->name, "op", "pincpu", "vcpu", buf,
+                  "cpumap", mapstr, NULL));
+}
+
+/**
+ * virDomainGetVcpus:
+ * @domain: pointer to domain object, or NULL for Domain0
+ * @info: pointer to an array of virVcpuInfo structures (OUT)
+ * @maxinfo: number of structures in info array
+ * @cpumaps: pointer to an bit map of real CPUs for all vcpus of this domain (in 8-bit bytes) (OUT)
+ *     If cpumaps is NULL, then no cupmap information is returned by the API.
+ *     It's assumed there is <maxinfo> cpumap in cpumaps array.
+ *     The memory allocated to cpumaps must be (maxinfo * maplen) bytes
+ *     (ie: calloc(maxinfo, maplen)).
+ *     One cpumap inside cpumaps has the format described in virDomainPinVcpu() API.
+ * @maplen: number of bytes in one cpumap, from 1 up to size of CPU map in
+ *     underlying virtualization system (Xen...).
+ * 
+ * Extract information about virtual CPUs of domain, store it in info array
+ * and also in cpumaps if this pointer is'nt NULL.
+ *
+ * Returns the number of info filled in case of success, -1 in case of failure.
+ */
+int
+xenDaemonDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
+                       unsigned char *cpumaps, int maplen)
+{
+    struct sexpr *root, *s, *t;
+    virVcpuInfoPtr ipt = info;
+    int nbinfo = 0, oln;
+    unsigned char *cpumap;
+    int vcpu, cpu;
+
+    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)
+     || (info == NULL) || (maxinfo < 1)) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                    __FUNCTION__);
+        return (-1);
+    }
+    if (cpumaps != NULL && maplen < 1) {
+        virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+                    __FUNCTION__);
+        return (-1);
+    }
+    root = sexpr_get(domain->conn, "/xend/domain/%s?op=vcpuinfo", domain->name);
+    if (root == NULL)
+        return (-1);
+
+    if (cpumaps != NULL)
+       memset(cpumaps, 0, maxinfo * maplen);
+
+    /* scan the sexprs from "(vcpu (number x)...)" and get parameter values */
+    for (s = root; s->kind == SEXPR_CONS; s = s->cdr)
+     if ((s->car->kind == SEXPR_CONS) &&
+        (s->car->car->kind == SEXPR_VALUE) &&
+        !strcmp(s->car->car->value, "vcpu")) {
+        t = s->car;
+        vcpu = ipt->number = sexpr_int(t, "vcpu/number");
+        if (oln = sexpr_int(t, "vcpu/online")) {
+            if (sexpr_int(t, "vcpu/running")) ipt->state = VIR_VCPU_RUNNING;
+            if (sexpr_int(t, "vcpu/blocked")) ipt->state = VIR_VCPU_BLOCKED;
+        }
+        else ipt->state = VIR_VCPU_OFFLINE;
+        ipt->cpuTime = sexpr_float(t, "vcpu/cpu_time") * 1000000000;
+        ipt->cpu = oln ? sexpr_int(t, "vcpu/cpu") : -1;
+
+       if (cpumaps != NULL && vcpu >= 0 && vcpu < maxinfo) {
+           cpumap = (unsigned char *) VIR_GET_CPUMAP(cpumaps, maplen, vcpu);
+            /*
+            * get sexpr from "(cpumap (x y z...))" and convert values
+            * to bitmap
+            */
+            for (t = t->cdr; t->kind == SEXPR_CONS; t = t->cdr)
+             if ((t->car->kind == SEXPR_CONS) &&
+                (t->car->car->kind == SEXPR_VALUE) &&
+                !strcmp(t->car->car->value, "cpumap") &&
+                (t->car->cdr->kind == SEXPR_CONS)) {
+               for (t = t->car->cdr->car; t->kind == SEXPR_CONS; t = t->cdr)
+                if (t->car->kind == SEXPR_VALUE) {
+                    cpu = strtol(t->car->value, NULL, 0);
+                   if (cpu >= 0)
+                       VIR_USE_CPU(cpumap, cpu);
+               }
+               break;
+            }
+       }
+
+        if (++nbinfo == maxinfo) break;
+        ipt++;
+    }
+    sexpr_free(root);
+    return(nbinfo);
+}
+
 /**
  * xenDaemonLookupByUUID:
  * @conn: pointer to the hypervisor connection
index 3806919a6c1084ba51513c1d29833d164865e12c..336913bca5177102d530ca7a026b0756a2bd0ec9 100644 (file)
@@ -631,6 +631,18 @@ virDomainPtr xenDaemonDomainLookupByName(virConnectPtr conn, const char *domname
 unsigned long xenDaemonDomainGetMaxMemory(virDomainPtr domain);
 char **xenDaemonListDomainsOld(virConnectPtr xend);
 
+int    xenDaemonDomainSetVcpus         (virDomainPtr domain,
+                                        int vcpus);
+int    xenDaemonDomainPinVcpu          (virDomainPtr domain,
+                                        unsigned int vcpu,
+                                        unsigned char *cpumap,
+                                        int maplen);
+int    xenDaemonDomainGetVcpus         (virDomainPtr domain,
+                                        virVcpuInfoPtr info,
+                                        int maxinfo,
+                                        unsigned char *cpumaps,
+                                        int maplen);
+
 #ifdef __cplusplus
 }
 #endif