From 3ebf7ca07e6906952de436d5e243834129bab8c0 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Mon, 20 Jun 2016 09:16:47 +0200 Subject: [PATCH] lib: Add API to set individual vcpu usage in the guest via guest agent To allow finer-grained control of vcpu state using guest agent this API can be used to individually set the state of the vCPU. This will allow to better control NUMA enabled guests and/or test various vCPU configurations. --- include/libvirt/libvirt-domain.h | 5 +++ src/driver-hypervisor.h | 7 ++++ src/libvirt-domain.c | 55 ++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 1 + src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 15 ++++++++- src/remote_protocol-structs | 7 ++++ 7 files changed, 90 insertions(+), 1 deletion(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 5605a94969..5b80b85246 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -4102,4 +4102,9 @@ int virDomainGetGuestVcpus(virDomainPtr domain, unsigned int *nparams, unsigned int flags); +int virDomainSetGuestVcpus(virDomainPtr domain, + const char *cpumap, + int state, + unsigned int flags); + #endif /* __VIR_LIBVIRT_DOMAIN_H__ */ diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index 93af2b664e..5cd1fdf4f3 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -1245,6 +1245,12 @@ typedef int unsigned int *nparams, unsigned int flags); +typedef int +(*virDrvDomainSetGuestVcpus)(virDomainPtr domain, + const char *cpumap, + int state, + unsigned int flags); + typedef struct _virHypervisorDriver virHypervisorDriver; typedef virHypervisorDriver *virHypervisorDriverPtr; @@ -1482,6 +1488,7 @@ struct _virHypervisorDriver { virDrvConnectUnregisterCloseCallback connectUnregisterCloseCallback; virDrvDomainMigrateStartPostCopy domainMigrateStartPostCopy; virDrvDomainGetGuestVcpus domainGetGuestVcpus; + virDrvDomainSetGuestVcpus domainSetGuestVcpus; }; diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index eb995b570f..508520efd6 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11891,3 +11891,58 @@ virDomainGetGuestVcpus(virDomainPtr domain, virDispatchError(domain->conn); return -1; } + + +/** + * virDomainSetGuestVcpus: + * @domain: pointer to domain object + * @cpumap: text representation of a bitmap of vcpus to set + * @state: 0 to disable/1 to enable cpus described by @cpumap + * @flags: currently unused, callers shall pass 0 + * + * Sets state of individual vcpus described by @cpumap via guest agent. Other + * vcpus are not modified. + * + * This API requires the VM to run. Various hypervisors or guest agent + * implementation may limit to operate on just 1 vCPU per call. + * + * @cpumap is a list of vCPU numbers. Its syntax is a comma separated list and + * a special markup using '-' and '^' (ex. '0-4', '0-3,^2'). The '-' denotes + * the range and the '^' denotes exclusive. The expression is sequentially + * evaluated, so "0-15,^8" is identical to "9-14,0-7,15" but not identical to + * "^8,0-15". + * + * Note that OSes (notably Linux) may require vCPU 0 to stay online to support + * low-level features a S3 sleep. + * + * Returns 0 on success, -1 on error. + */ +int +virDomainSetGuestVcpus(virDomainPtr domain, + const char *cpumap, + int state, + unsigned int flags) +{ + VIR_DOMAIN_DEBUG(domain, "cpumap='%s' state=%x flags=%x", + NULLSTR(cpumap), state, flags); + + virResetLastError(); + + virCheckDomainReturn(domain, -1); + virCheckNonNullArgGoto(cpumap, error); + + if (domain->conn->driver->domainSetGuestVcpus) { + int ret; + ret = domain->conn->driver->domainSetGuestVcpus(domain, cpumap, state, + flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(domain->conn); + return -1; +} diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 30801c5a54..b6d2dfdba3 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -737,6 +737,7 @@ LIBVIRT_2.0.0 { virConnectStoragePoolEventRegisterAny; virConnectStoragePoolEventDeregisterAny; virDomainGetGuestVcpus; + virDomainSetGuestVcpus; } LIBVIRT_1.3.3; # .... define new API here using predicted next version number .... diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 6a580c6c01..3f9d812fc9 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -7982,6 +7982,7 @@ static virHypervisorDriver hypervisor_driver = { .connectUnregisterCloseCallback = remoteConnectUnregisterCloseCallback, /* 1.3.2 */ .domainMigrateStartPostCopy = remoteDomainMigrateStartPostCopy, /* 1.3.3 */ .domainGetGuestVcpus = remoteDomainGetGuestVcpus, /* 2.0.0 */ + .domainSetGuestVcpus = remoteDomainSetGuestVcpus, /* 2.0.0 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index f72918d2e3..d11bfdf699 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3304,6 +3304,13 @@ struct remote_domain_get_guest_vcpus_ret { remote_typed_param params; /* alloc@1@unsigned int@2 */ }; +struct remote_domain_set_guest_vcpus_args { + remote_nonnull_domain dom; + remote_nonnull_string cpumap; + int state; + unsigned int flags; +}; + /*----- Protocol. -----*/ @@ -5858,5 +5865,11 @@ enum remote_procedure { * @generate: both * @acl: domain:write */ - REMOTE_PROC_DOMAIN_GET_GUEST_VCPUS = 371 + REMOTE_PROC_DOMAIN_GET_GUEST_VCPUS = 371, + + /** + * @generate: both + * @acl: domain:write + */ + REMOTE_PROC_DOMAIN_SET_GUEST_VCPUS = 372 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 4e603dbe52..0d89b15c21 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2761,6 +2761,12 @@ struct remote_domain_get_guest_vcpus_ret { remote_typed_param * params_val; } params; }; +struct remote_domain_set_guest_vcpus_args { + remote_nonnull_domain dom; + remote_nonnull_string cpumap; + int state; + u_int flags; +}; enum remote_procedure { REMOTE_PROC_CONNECT_OPEN = 1, REMOTE_PROC_CONNECT_CLOSE = 2, @@ -3133,4 +3139,5 @@ enum remote_procedure { REMOTE_PROC_CONNECT_STORAGE_POOL_EVENT_DEREGISTER_ANY = 369, REMOTE_PROC_STORAGE_POOL_EVENT_LIFECYCLE = 370, REMOTE_PROC_DOMAIN_GET_GUEST_VCPUS = 371, + REMOTE_PROC_DOMAIN_SET_GUEST_VCPUS = 372, };