+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
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
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
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);
+}
virConnResetLastError;
virDefaultErrorFunc;
virNodeGetInfo;
+
+ virDomainSetVcpus;
+ virDomainPinVcpu;
+ virDomainGetVcpus;
local: *;
};
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
-
+#include <limits.h>
#include <stdint.h>
/* required for dom0_getdomaininfo_t */
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;
+}
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
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 );
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
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