mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 18:21:39 +01:00
Move calls that require a information about a single precisely identified domain to the new xc_domain_getinfo_single(). Signed-off-by: Alejandro Vallejo <alejandro.vallejo@cloud.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> Acked-by: Anthony PERARD <anthony.perard@citrix.com>
983 lines
28 KiB
C
983 lines
28 KiB
C
/*
|
|
* Copyright 2009-2017 Citrix Ltd and other contributors
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation; version 2.1 only. with the special
|
|
* exception on linking described in file LICENSE.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*/
|
|
|
|
#include "libxl_osdeps.h"
|
|
|
|
#include "libxl_internal.h"
|
|
|
|
static int libxl__set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid,
|
|
uint32_t vcpuid,
|
|
const libxl_bitmap *cpumap_hard,
|
|
const libxl_bitmap *cpumap_soft,
|
|
unsigned flags)
|
|
{
|
|
GC_INIT(ctx);
|
|
libxl_bitmap hard, soft;
|
|
int rc;
|
|
|
|
libxl_bitmap_init(&hard);
|
|
libxl_bitmap_init(&soft);
|
|
|
|
if (!cpumap_hard && !cpumap_soft && !flags) {
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
|
|
/*
|
|
* Xen wants writable hard and/or soft cpumaps, to put back in them
|
|
* the effective hard and/or soft affinity that will be used.
|
|
*/
|
|
if (cpumap_hard) {
|
|
rc = libxl_cpu_bitmap_alloc(ctx, &hard, 0);
|
|
if (rc)
|
|
goto out;
|
|
|
|
libxl__bitmap_copy_best_effort(gc, &hard, cpumap_hard);
|
|
flags |= XEN_VCPUAFFINITY_HARD;
|
|
}
|
|
if (cpumap_soft) {
|
|
rc = libxl_cpu_bitmap_alloc(ctx, &soft, 0);
|
|
if (rc)
|
|
goto out;
|
|
|
|
libxl__bitmap_copy_best_effort(gc, &soft, cpumap_soft);
|
|
flags |= XEN_VCPUAFFINITY_SOFT;
|
|
}
|
|
|
|
if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid,
|
|
cpumap_hard ? hard.map : NULL,
|
|
cpumap_soft ? soft.map : NULL,
|
|
flags)) {
|
|
LOGED(ERROR, domid, "Setting vcpu affinity");
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
/*
|
|
* Let's check the results. Hard affinity will never be empty, but it
|
|
* is possible that Xen will use something different from what we asked
|
|
* for various reasons. If that's the case, report it.
|
|
*/
|
|
if (cpumap_hard &&
|
|
!libxl_bitmap_equal(cpumap_hard, &hard, 0))
|
|
LOGD(DEBUG, domid, "New hard affinity for vcpu %d has unreachable cpus", vcpuid);
|
|
/*
|
|
* Soft affinity can both be different from what asked and empty. Check
|
|
* for (and report) both.
|
|
*/
|
|
if (cpumap_soft) {
|
|
if (!libxl_bitmap_equal(cpumap_soft, &soft, 0))
|
|
LOGD(DEBUG, domid, "New soft affinity for vcpu %d has unreachable cpus",
|
|
vcpuid);
|
|
if (libxl_bitmap_is_empty(&soft))
|
|
LOGD(WARN, domid, "All cpus in soft affinity of vcpu %d are unreachable."
|
|
" Only hard affinity will be considered for scheduling",
|
|
vcpuid);
|
|
}
|
|
|
|
rc = 0;
|
|
out:
|
|
libxl_bitmap_dispose(&hard);
|
|
libxl_bitmap_dispose(&soft);
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid,
|
|
const libxl_bitmap *cpumap_hard,
|
|
const libxl_bitmap *cpumap_soft)
|
|
{
|
|
return libxl__set_vcpuaffinity(ctx, domid, vcpuid, cpumap_hard,
|
|
cpumap_soft, 0);
|
|
}
|
|
|
|
int libxl_set_vcpuaffinity_force(libxl_ctx *ctx, uint32_t domid,
|
|
uint32_t vcpuid,
|
|
const libxl_bitmap *cpumap_hard,
|
|
const libxl_bitmap *cpumap_soft)
|
|
{
|
|
return libxl__set_vcpuaffinity(ctx, domid, vcpuid, cpumap_hard,
|
|
cpumap_soft, XEN_VCPUAFFINITY_FORCE);
|
|
}
|
|
|
|
int libxl_set_vcpuaffinity_all(libxl_ctx *ctx, uint32_t domid,
|
|
unsigned int max_vcpus,
|
|
const libxl_bitmap *cpumap_hard,
|
|
const libxl_bitmap *cpumap_soft)
|
|
{
|
|
GC_INIT(ctx);
|
|
int i, rc = 0;
|
|
|
|
for (i = 0; i < max_vcpus; i++) {
|
|
if (libxl_set_vcpuaffinity(ctx, domid, i, cpumap_hard, cpumap_soft)) {
|
|
LOGD(WARN, domid, "Failed to set affinity for %d", i);
|
|
rc = ERROR_FAIL;
|
|
}
|
|
}
|
|
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
int libxl_domain_set_nodeaffinity(libxl_ctx *ctx, uint32_t domid,
|
|
libxl_bitmap *nodemap)
|
|
{
|
|
GC_INIT(ctx);
|
|
if (xc_domain_node_setaffinity(ctx->xch, domid, nodemap->map)) {
|
|
LOGED(ERROR, domid, "Setting node affinity");
|
|
GC_FREE;
|
|
return ERROR_FAIL;
|
|
}
|
|
GC_FREE;
|
|
return 0;
|
|
}
|
|
|
|
int libxl_domain_get_nodeaffinity(libxl_ctx *ctx, uint32_t domid,
|
|
libxl_bitmap *nodemap)
|
|
{
|
|
GC_INIT(ctx);
|
|
if (xc_domain_node_getaffinity(ctx->xch, domid, nodemap->map)) {
|
|
LOGED(ERROR, domid, "Getting node affinity");
|
|
GC_FREE;
|
|
return ERROR_FAIL;
|
|
}
|
|
GC_FREE;
|
|
return 0;
|
|
}
|
|
|
|
int libxl_get_scheduler(libxl_ctx *ctx)
|
|
{
|
|
int r, sched;
|
|
|
|
GC_INIT(ctx);
|
|
r = xc_sched_id(ctx->xch, &sched);
|
|
if (r != 0) {
|
|
LOGE(ERROR, "getting current scheduler id");
|
|
sched = ERROR_FAIL;
|
|
}
|
|
GC_FREE;
|
|
return sched;
|
|
}
|
|
|
|
static int sched_arinc653_domain_set(libxl__gc *gc, uint32_t domid,
|
|
const libxl_domain_sched_params *scinfo)
|
|
{
|
|
/* Currently, the ARINC 653 scheduler does not take any domain-specific
|
|
configuration, so we simply return success. */
|
|
return 0;
|
|
}
|
|
|
|
static int sched_null_domain_set(libxl__gc *gc, uint32_t domid,
|
|
const libxl_domain_sched_params *scinfo)
|
|
{
|
|
/* There aren't any domain-specific parameters to be set. */
|
|
return 0;
|
|
}
|
|
|
|
static int sched_null_domain_get(libxl__gc *gc, uint32_t domid,
|
|
libxl_domain_sched_params *scinfo)
|
|
{
|
|
/* There aren't any domain-specific parameters to return. */
|
|
return 0;
|
|
}
|
|
|
|
static int sched_credit_domain_get(libxl__gc *gc, uint32_t domid,
|
|
libxl_domain_sched_params *scinfo)
|
|
{
|
|
struct xen_domctl_sched_credit sdom;
|
|
int rc;
|
|
|
|
rc = xc_sched_credit_domain_get(CTX->xch, domid, &sdom);
|
|
if (rc != 0) {
|
|
LOGED(ERROR, domid, "Getting domain sched credit");
|
|
return ERROR_FAIL;
|
|
}
|
|
|
|
libxl_domain_sched_params_init(scinfo);
|
|
scinfo->sched = LIBXL_SCHEDULER_CREDIT;
|
|
scinfo->weight = sdom.weight;
|
|
scinfo->cap = sdom.cap;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sched_credit_domain_set(libxl__gc *gc, uint32_t domid,
|
|
const libxl_domain_sched_params *scinfo)
|
|
{
|
|
struct xen_domctl_sched_credit sdom;
|
|
xc_domaininfo_t domaininfo;
|
|
int rc;
|
|
|
|
rc = xc_domain_getinfo_single(CTX->xch, domid, &domaininfo);
|
|
if (rc < 0) {
|
|
LOGED(ERROR, domid, "Getting domain info");
|
|
return errno == ESRCH ? ERROR_INVAL : ERROR_FAIL;
|
|
}
|
|
|
|
rc = xc_sched_credit_domain_get(CTX->xch, domid, &sdom);
|
|
if (rc != 0) {
|
|
LOGED(ERROR, domid, "Getting domain sched credit");
|
|
return ERROR_FAIL;
|
|
}
|
|
|
|
if (scinfo->weight != LIBXL_DOMAIN_SCHED_PARAM_WEIGHT_DEFAULT) {
|
|
if (scinfo->weight < 1 || scinfo->weight > 65535) {
|
|
LOGD(ERROR, domid, "Cpu weight out of range, "
|
|
"valid values are within range from 1 to 65535");
|
|
return ERROR_INVAL;
|
|
}
|
|
sdom.weight = scinfo->weight;
|
|
}
|
|
|
|
if (scinfo->cap != LIBXL_DOMAIN_SCHED_PARAM_CAP_DEFAULT) {
|
|
if (scinfo->cap < 0
|
|
|| scinfo->cap > (domaininfo.max_vcpu_id + 1) * 100) {
|
|
LOGD(ERROR, domid, "Cpu cap out of range, "
|
|
"valid range is from 0 to %d for specified number of vcpus",
|
|
((domaininfo.max_vcpu_id + 1) * 100));
|
|
return ERROR_INVAL;
|
|
}
|
|
sdom.cap = scinfo->cap;
|
|
}
|
|
|
|
rc = xc_sched_credit_domain_set(CTX->xch, domid, &sdom);
|
|
if ( rc < 0 ) {
|
|
LOGED(ERROR, domid, "Setting domain sched credit");
|
|
return ERROR_FAIL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sched_ratelimit_check(libxl__gc *gc, int ratelimit)
|
|
{
|
|
if (ratelimit != 0 &&
|
|
(ratelimit < XEN_SYSCTL_SCHED_RATELIMIT_MIN ||
|
|
ratelimit > XEN_SYSCTL_SCHED_RATELIMIT_MAX)) {
|
|
LOG(ERROR, "Ratelimit out of range, valid range is from %d to %d",
|
|
XEN_SYSCTL_SCHED_RATELIMIT_MIN, XEN_SYSCTL_SCHED_RATELIMIT_MAX);
|
|
return ERROR_INVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int libxl_sched_credit_params_get(libxl_ctx *ctx, uint32_t poolid,
|
|
libxl_sched_credit_params *scinfo)
|
|
{
|
|
struct xen_sysctl_credit_schedule sparam;
|
|
int r, rc;
|
|
GC_INIT(ctx);
|
|
|
|
r = xc_sched_credit_params_get(ctx->xch, poolid, &sparam);
|
|
if (r < 0) {
|
|
LOGE(ERROR, "getting Credit scheduler parameters");
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
scinfo->tslice_ms = sparam.tslice_ms;
|
|
scinfo->ratelimit_us = sparam.ratelimit_us;
|
|
scinfo->vcpu_migr_delay_us = sparam.vcpu_migr_delay_us;
|
|
|
|
rc = 0;
|
|
out:
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
int libxl_sched_credit_params_set(libxl_ctx *ctx, uint32_t poolid,
|
|
libxl_sched_credit_params *scinfo)
|
|
{
|
|
struct xen_sysctl_credit_schedule sparam;
|
|
int r, rc;
|
|
GC_INIT(ctx);
|
|
|
|
if (scinfo->tslice_ms < XEN_SYSCTL_CSCHED_TSLICE_MIN
|
|
|| scinfo->tslice_ms > XEN_SYSCTL_CSCHED_TSLICE_MAX) {
|
|
LOG(ERROR, "Time slice out of range, valid range is from %d to %d",
|
|
XEN_SYSCTL_CSCHED_TSLICE_MIN, XEN_SYSCTL_CSCHED_TSLICE_MAX);
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
rc = sched_ratelimit_check(gc, scinfo->ratelimit_us);
|
|
if (rc) {
|
|
goto out;
|
|
}
|
|
if (scinfo->ratelimit_us > scinfo->tslice_ms*1000) {
|
|
LOG(ERROR, "Ratelimit cannot be greater than timeslice");
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
if (scinfo->vcpu_migr_delay_us > XEN_SYSCTL_CSCHED_MGR_DLY_MAX_US) {
|
|
LOG(ERROR, "vcpu migration delay should be >= 0 and <= %dus",
|
|
XEN_SYSCTL_CSCHED_MGR_DLY_MAX_US);
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
|
|
sparam.tslice_ms = scinfo->tslice_ms;
|
|
sparam.ratelimit_us = scinfo->ratelimit_us;
|
|
sparam.vcpu_migr_delay_us = scinfo->vcpu_migr_delay_us;
|
|
|
|
r = xc_sched_credit_params_set(ctx->xch, poolid, &sparam);
|
|
if ( r < 0 ) {
|
|
LOGE(ERROR, "Setting Credit scheduler parameters");
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
scinfo->tslice_ms = sparam.tslice_ms;
|
|
scinfo->ratelimit_us = sparam.ratelimit_us;
|
|
scinfo->vcpu_migr_delay_us = sparam.vcpu_migr_delay_us;
|
|
|
|
rc = 0;
|
|
out:
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
int libxl_sched_credit2_params_get(libxl_ctx *ctx, uint32_t poolid,
|
|
libxl_sched_credit2_params *scinfo)
|
|
{
|
|
struct xen_sysctl_credit2_schedule sparam;
|
|
int r, rc;
|
|
GC_INIT(ctx);
|
|
|
|
r = xc_sched_credit2_params_get(ctx->xch, poolid, &sparam);
|
|
if (r < 0) {
|
|
LOGE(ERROR, "getting Credit2 scheduler parameters");
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
scinfo->ratelimit_us = sparam.ratelimit_us;
|
|
|
|
rc = 0;
|
|
out:
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
int libxl_sched_credit2_params_set(libxl_ctx *ctx, uint32_t poolid,
|
|
libxl_sched_credit2_params *scinfo)
|
|
{
|
|
struct xen_sysctl_credit2_schedule sparam;
|
|
int r, rc;
|
|
GC_INIT(ctx);
|
|
|
|
rc = sched_ratelimit_check(gc, scinfo->ratelimit_us);
|
|
if (rc) goto out;
|
|
|
|
sparam.ratelimit_us = scinfo->ratelimit_us;
|
|
|
|
r = xc_sched_credit2_params_set(ctx->xch, poolid, &sparam);
|
|
if (r < 0) {
|
|
LOGE(ERROR, "Setting Credit2 scheduler parameters");
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
scinfo->ratelimit_us = sparam.ratelimit_us;
|
|
|
|
rc = 0;
|
|
out:
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
static int sched_credit2_domain_get(libxl__gc *gc, uint32_t domid,
|
|
libxl_domain_sched_params *scinfo)
|
|
{
|
|
struct xen_domctl_sched_credit2 sdom;
|
|
int rc;
|
|
|
|
rc = xc_sched_credit2_domain_get(CTX->xch, domid, &sdom);
|
|
if (rc != 0) {
|
|
LOGED(ERROR, domid, "Getting domain sched credit2");
|
|
return ERROR_FAIL;
|
|
}
|
|
|
|
libxl_domain_sched_params_init(scinfo);
|
|
scinfo->sched = LIBXL_SCHEDULER_CREDIT2;
|
|
scinfo->weight = sdom.weight;
|
|
scinfo->cap = sdom.cap;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sched_credit2_domain_set(libxl__gc *gc, uint32_t domid,
|
|
const libxl_domain_sched_params *scinfo)
|
|
{
|
|
struct xen_domctl_sched_credit2 sdom;
|
|
xc_domaininfo_t info;
|
|
int rc;
|
|
|
|
rc = xc_domain_getinfo_single(CTX->xch, domid, &info);
|
|
if (rc < 0) {
|
|
LOGED(ERROR, domid, "Getting domain info");
|
|
return errno == ESRCH ? ERROR_INVAL : ERROR_FAIL;
|
|
}
|
|
|
|
rc = xc_sched_credit2_domain_get(CTX->xch, domid, &sdom);
|
|
if (rc != 0) {
|
|
LOGED(ERROR, domid, "Getting domain sched credit2");
|
|
return ERROR_FAIL;
|
|
}
|
|
|
|
if (scinfo->weight != LIBXL_DOMAIN_SCHED_PARAM_WEIGHT_DEFAULT) {
|
|
if (scinfo->weight < 1 || scinfo->weight > 65535) {
|
|
LOGD(ERROR, domid, "Cpu weight out of range, "
|
|
"valid values are within range from 1 to 65535");
|
|
return ERROR_INVAL;
|
|
}
|
|
sdom.weight = scinfo->weight;
|
|
}
|
|
|
|
if (scinfo->cap != LIBXL_DOMAIN_SCHED_PARAM_CAP_DEFAULT) {
|
|
if (scinfo->cap < 0
|
|
|| scinfo->cap > (info.max_vcpu_id + 1) * 100) {
|
|
LOGD(ERROR, domid, "Cpu cap out of range, "
|
|
"valid range is from 0 to %d for specified number of vcpus",
|
|
((info.max_vcpu_id + 1) * 100));
|
|
return ERROR_INVAL;
|
|
}
|
|
sdom.cap = scinfo->cap;
|
|
}
|
|
|
|
rc = xc_sched_credit2_domain_set(CTX->xch, domid, &sdom);
|
|
if ( rc < 0 ) {
|
|
LOGED(ERROR, domid, "Setting domain sched credit2");
|
|
return ERROR_FAIL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sched_rtds_validate_params(libxl__gc *gc, int period, int budget)
|
|
{
|
|
int rc;
|
|
|
|
if (period < 1) {
|
|
LOG(ERROR, "Invalid VCPU period of %d (it should be >= 1)", period);
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
|
|
if (budget < 1) {
|
|
LOG(ERROR, "Invalid VCPU budget of %d (it should be >= 1)", budget);
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
|
|
if (budget > period) {
|
|
LOG(ERROR, "VCPU budget must be smaller than or equal to period, "
|
|
"but %d > %d", budget, period);
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
rc = 0;
|
|
out:
|
|
return rc;
|
|
}
|
|
|
|
/* Get the RTDS scheduling parameters of vcpu(s) */
|
|
static int sched_rtds_vcpu_get(libxl__gc *gc, uint32_t domid,
|
|
libxl_vcpu_sched_params *scinfo)
|
|
{
|
|
uint32_t num_vcpus;
|
|
int i, r, rc;
|
|
xc_domaininfo_t info;
|
|
struct xen_domctl_schedparam_vcpu *vcpus;
|
|
|
|
r = xc_domain_getinfo_single(CTX->xch, domid, &info);
|
|
if (r < 0) {
|
|
LOGED(ERROR, domid, "Getting domain info");
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
if (scinfo->num_vcpus <= 0) {
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
} else {
|
|
num_vcpus = scinfo->num_vcpus;
|
|
GCNEW_ARRAY(vcpus, num_vcpus);
|
|
for (i = 0; i < num_vcpus; i++) {
|
|
if (scinfo->vcpus[i].vcpuid < 0 ||
|
|
scinfo->vcpus[i].vcpuid > info.max_vcpu_id) {
|
|
LOGD(ERROR, domid, "VCPU index is out of range, "
|
|
"valid values are within range from 0 to %d",
|
|
info.max_vcpu_id);
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
vcpus[i].vcpuid = scinfo->vcpus[i].vcpuid;
|
|
}
|
|
}
|
|
|
|
r = xc_sched_rtds_vcpu_get(CTX->xch, domid, vcpus, num_vcpus);
|
|
if (r != 0) {
|
|
LOGED(ERROR, domid, "Getting vcpu sched rtds");
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
scinfo->sched = LIBXL_SCHEDULER_RTDS;
|
|
for (i = 0; i < num_vcpus; i++) {
|
|
scinfo->vcpus[i].period = vcpus[i].u.rtds.period;
|
|
scinfo->vcpus[i].budget = vcpus[i].u.rtds.budget;
|
|
scinfo->vcpus[i].extratime =
|
|
!!(vcpus[i].u.rtds.flags & XEN_DOMCTL_SCHEDRT_extra);
|
|
scinfo->vcpus[i].vcpuid = vcpus[i].vcpuid;
|
|
}
|
|
rc = 0;
|
|
out:
|
|
return rc;
|
|
}
|
|
|
|
/* Get the RTDS scheduling parameters of all vcpus of a domain */
|
|
static int sched_rtds_vcpu_get_all(libxl__gc *gc, uint32_t domid,
|
|
libxl_vcpu_sched_params *scinfo)
|
|
{
|
|
uint32_t num_vcpus;
|
|
int i, r, rc;
|
|
xc_domaininfo_t info;
|
|
struct xen_domctl_schedparam_vcpu *vcpus;
|
|
|
|
r = xc_domain_getinfo_single(CTX->xch, domid, &info);
|
|
if (r < 0) {
|
|
LOGED(ERROR, domid, "Getting domain info");
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
if (scinfo->num_vcpus > 0) {
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
} else {
|
|
num_vcpus = info.max_vcpu_id + 1;
|
|
GCNEW_ARRAY(vcpus, num_vcpus);
|
|
for (i = 0; i < num_vcpus; i++)
|
|
vcpus[i].vcpuid = i;
|
|
}
|
|
|
|
r = xc_sched_rtds_vcpu_get(CTX->xch, domid, vcpus, num_vcpus);
|
|
if (r != 0) {
|
|
LOGED(ERROR, domid, "Getting vcpu sched rtds");
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
scinfo->sched = LIBXL_SCHEDULER_RTDS;
|
|
scinfo->num_vcpus = num_vcpus;
|
|
scinfo->vcpus = libxl__calloc(NOGC, num_vcpus,
|
|
sizeof(libxl_sched_params));
|
|
|
|
for (i = 0; i < num_vcpus; i++) {
|
|
scinfo->vcpus[i].period = vcpus[i].u.rtds.period;
|
|
scinfo->vcpus[i].budget = vcpus[i].u.rtds.budget;
|
|
scinfo->vcpus[i].extratime =
|
|
!!(vcpus[i].u.rtds.flags & XEN_DOMCTL_SCHEDRT_extra);
|
|
scinfo->vcpus[i].vcpuid = vcpus[i].vcpuid;
|
|
}
|
|
rc = 0;
|
|
out:
|
|
return rc;
|
|
}
|
|
|
|
/* Set the RTDS scheduling parameters of vcpu(s) */
|
|
static int sched_rtds_vcpu_set(libxl__gc *gc, uint32_t domid,
|
|
const libxl_vcpu_sched_params *scinfo)
|
|
{
|
|
int r, rc;
|
|
int i;
|
|
uint16_t max_vcpuid;
|
|
xc_domaininfo_t info;
|
|
struct xen_domctl_schedparam_vcpu *vcpus;
|
|
|
|
r = xc_domain_getinfo_single(CTX->xch, domid, &info);
|
|
if (r < 0) {
|
|
LOGED(ERROR, domid, "Getting domain info");
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
max_vcpuid = info.max_vcpu_id;
|
|
|
|
if (scinfo->num_vcpus <= 0) {
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
for (i = 0; i < scinfo->num_vcpus; i++) {
|
|
if (scinfo->vcpus[i].vcpuid < 0 ||
|
|
scinfo->vcpus[i].vcpuid > max_vcpuid) {
|
|
LOGD(ERROR, domid, "Invalid VCPU %d: valid range is [0, %d]",
|
|
scinfo->vcpus[i].vcpuid, max_vcpuid);
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
rc = sched_rtds_validate_params(gc, scinfo->vcpus[i].period,
|
|
scinfo->vcpus[i].budget);
|
|
if (rc) {
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
}
|
|
GCNEW_ARRAY(vcpus, scinfo->num_vcpus);
|
|
for (i = 0; i < scinfo->num_vcpus; i++) {
|
|
vcpus[i].vcpuid = scinfo->vcpus[i].vcpuid;
|
|
vcpus[i].u.rtds.period = scinfo->vcpus[i].period;
|
|
vcpus[i].u.rtds.budget = scinfo->vcpus[i].budget;
|
|
if (scinfo->vcpus[i].extratime)
|
|
vcpus[i].u.rtds.flags |= XEN_DOMCTL_SCHEDRT_extra;
|
|
else
|
|
vcpus[i].u.rtds.flags &= ~XEN_DOMCTL_SCHEDRT_extra;
|
|
}
|
|
|
|
r = xc_sched_rtds_vcpu_set(CTX->xch, domid,
|
|
vcpus, scinfo->num_vcpus);
|
|
if (r != 0) {
|
|
LOGED(ERROR, domid, "Setting vcpu sched rtds");
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
rc = 0;
|
|
out:
|
|
return rc;
|
|
}
|
|
|
|
/* Set the RTDS scheduling parameters of all vcpus of a domain */
|
|
static int sched_rtds_vcpu_set_all(libxl__gc *gc, uint32_t domid,
|
|
const libxl_vcpu_sched_params *scinfo)
|
|
{
|
|
int r, rc;
|
|
int i;
|
|
uint16_t max_vcpuid;
|
|
xc_domaininfo_t info;
|
|
struct xen_domctl_schedparam_vcpu *vcpus;
|
|
uint32_t num_vcpus;
|
|
|
|
r = xc_domain_getinfo_single(CTX->xch, domid, &info);
|
|
if (r < 0) {
|
|
LOGED(ERROR, domid, "Getting domain info");
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
max_vcpuid = info.max_vcpu_id;
|
|
|
|
if (scinfo->num_vcpus != 1) {
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
if (sched_rtds_validate_params(gc, scinfo->vcpus[0].period,
|
|
scinfo->vcpus[0].budget)) {
|
|
rc = ERROR_INVAL;
|
|
goto out;
|
|
}
|
|
num_vcpus = max_vcpuid + 1;
|
|
GCNEW_ARRAY(vcpus, num_vcpus);
|
|
for (i = 0; i < num_vcpus; i++) {
|
|
vcpus[i].vcpuid = i;
|
|
vcpus[i].u.rtds.period = scinfo->vcpus[0].period;
|
|
vcpus[i].u.rtds.budget = scinfo->vcpus[0].budget;
|
|
if (scinfo->vcpus[0].extratime)
|
|
vcpus[i].u.rtds.flags |= XEN_DOMCTL_SCHEDRT_extra;
|
|
else
|
|
vcpus[i].u.rtds.flags &= ~XEN_DOMCTL_SCHEDRT_extra;
|
|
}
|
|
|
|
r = xc_sched_rtds_vcpu_set(CTX->xch, domid,
|
|
vcpus, num_vcpus);
|
|
if (r != 0) {
|
|
LOGED(ERROR, domid, "Setting vcpu sched rtds");
|
|
rc = ERROR_FAIL;
|
|
goto out;
|
|
}
|
|
rc = 0;
|
|
out:
|
|
return rc;
|
|
}
|
|
|
|
static int sched_rtds_domain_get(libxl__gc *gc, uint32_t domid,
|
|
libxl_domain_sched_params *scinfo)
|
|
{
|
|
struct xen_domctl_sched_rtds sdom;
|
|
int rc;
|
|
|
|
rc = xc_sched_rtds_domain_get(CTX->xch, domid, &sdom);
|
|
if (rc != 0) {
|
|
LOGED(ERROR, domid, "Getting domain sched rtds");
|
|
return ERROR_FAIL;
|
|
}
|
|
|
|
libxl_domain_sched_params_init(scinfo);
|
|
|
|
scinfo->sched = LIBXL_SCHEDULER_RTDS;
|
|
scinfo->period = sdom.period;
|
|
scinfo->budget = sdom.budget;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sched_rtds_domain_set(libxl__gc *gc, uint32_t domid,
|
|
const libxl_domain_sched_params *scinfo)
|
|
{
|
|
struct xen_domctl_sched_rtds sdom;
|
|
int rc;
|
|
|
|
rc = xc_sched_rtds_domain_get(CTX->xch, domid, &sdom);
|
|
if (rc != 0) {
|
|
LOGED(ERROR, domid, "Getting domain sched rtds");
|
|
return ERROR_FAIL;
|
|
}
|
|
if (scinfo->period != LIBXL_DOMAIN_SCHED_PARAM_PERIOD_DEFAULT)
|
|
sdom.period = scinfo->period;
|
|
if (scinfo->budget != LIBXL_DOMAIN_SCHED_PARAM_BUDGET_DEFAULT)
|
|
sdom.budget = scinfo->budget;
|
|
/* Set extratime by default */
|
|
if (scinfo->extratime)
|
|
sdom.flags |= XEN_DOMCTL_SCHEDRT_extra;
|
|
else
|
|
sdom.flags &= ~XEN_DOMCTL_SCHEDRT_extra;
|
|
if (sched_rtds_validate_params(gc, sdom.period, sdom.budget))
|
|
return ERROR_INVAL;
|
|
|
|
rc = xc_sched_rtds_domain_set(CTX->xch, domid, &sdom);
|
|
if (rc < 0) {
|
|
LOGED(ERROR, domid, "Setting domain sched rtds");
|
|
return ERROR_FAIL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int libxl_domain_sched_params_set(libxl_ctx *ctx, uint32_t domid,
|
|
const libxl_domain_sched_params *scinfo)
|
|
{
|
|
GC_INIT(ctx);
|
|
libxl_scheduler sched = scinfo->sched;
|
|
int ret;
|
|
|
|
if (sched == LIBXL_SCHEDULER_UNKNOWN)
|
|
sched = libxl__domain_scheduler(gc, domid);
|
|
|
|
switch (sched) {
|
|
case LIBXL_SCHEDULER_SEDF:
|
|
LOGD(ERROR, domid, "SEDF scheduler no longer available");
|
|
ret=ERROR_FEATURE_REMOVED;
|
|
break;
|
|
case LIBXL_SCHEDULER_CREDIT:
|
|
ret=sched_credit_domain_set(gc, domid, scinfo);
|
|
break;
|
|
case LIBXL_SCHEDULER_CREDIT2:
|
|
ret=sched_credit2_domain_set(gc, domid, scinfo);
|
|
break;
|
|
case LIBXL_SCHEDULER_ARINC653:
|
|
ret=sched_arinc653_domain_set(gc, domid, scinfo);
|
|
break;
|
|
case LIBXL_SCHEDULER_RTDS:
|
|
ret=sched_rtds_domain_set(gc, domid, scinfo);
|
|
break;
|
|
case LIBXL_SCHEDULER_NULL:
|
|
ret=sched_null_domain_set(gc, domid, scinfo);
|
|
break;
|
|
default:
|
|
LOGD(ERROR, domid, "Unknown scheduler");
|
|
ret=ERROR_INVAL;
|
|
break;
|
|
}
|
|
|
|
GC_FREE;
|
|
return ret;
|
|
}
|
|
|
|
int libxl_vcpu_sched_params_set(libxl_ctx *ctx, uint32_t domid,
|
|
const libxl_vcpu_sched_params *scinfo)
|
|
{
|
|
GC_INIT(ctx);
|
|
libxl_scheduler sched = scinfo->sched;
|
|
int rc;
|
|
|
|
if (sched == LIBXL_SCHEDULER_UNKNOWN)
|
|
sched = libxl__domain_scheduler(gc, domid);
|
|
|
|
switch (sched) {
|
|
case LIBXL_SCHEDULER_SEDF:
|
|
LOGD(ERROR, domid, "SEDF scheduler no longer available");
|
|
rc = ERROR_FEATURE_REMOVED;
|
|
break;
|
|
case LIBXL_SCHEDULER_CREDIT:
|
|
case LIBXL_SCHEDULER_CREDIT2:
|
|
case LIBXL_SCHEDULER_ARINC653:
|
|
case LIBXL_SCHEDULER_NULL:
|
|
LOGD(ERROR, domid, "per-VCPU parameter setting not supported for this scheduler");
|
|
rc = ERROR_INVAL;
|
|
break;
|
|
case LIBXL_SCHEDULER_RTDS:
|
|
rc = sched_rtds_vcpu_set(gc, domid, scinfo);
|
|
break;
|
|
default:
|
|
LOGD(ERROR, domid, "Unknown scheduler");
|
|
rc = ERROR_INVAL;
|
|
break;
|
|
}
|
|
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
int libxl_vcpu_sched_params_set_all(libxl_ctx *ctx, uint32_t domid,
|
|
const libxl_vcpu_sched_params *scinfo)
|
|
{
|
|
GC_INIT(ctx);
|
|
libxl_scheduler sched = scinfo->sched;
|
|
int rc;
|
|
|
|
if (sched == LIBXL_SCHEDULER_UNKNOWN)
|
|
sched = libxl__domain_scheduler(gc, domid);
|
|
|
|
switch (sched) {
|
|
case LIBXL_SCHEDULER_SEDF:
|
|
LOGD(ERROR, domid, "SEDF scheduler no longer available");
|
|
rc = ERROR_FEATURE_REMOVED;
|
|
break;
|
|
case LIBXL_SCHEDULER_CREDIT:
|
|
case LIBXL_SCHEDULER_CREDIT2:
|
|
case LIBXL_SCHEDULER_ARINC653:
|
|
case LIBXL_SCHEDULER_NULL:
|
|
LOGD(ERROR, domid, "per-VCPU parameter setting not supported for this scheduler");
|
|
rc = ERROR_INVAL;
|
|
break;
|
|
case LIBXL_SCHEDULER_RTDS:
|
|
rc = sched_rtds_vcpu_set_all(gc, domid, scinfo);
|
|
break;
|
|
default:
|
|
LOGD(ERROR, domid, "Unknown scheduler");
|
|
rc = ERROR_INVAL;
|
|
break;
|
|
}
|
|
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
int libxl_domain_sched_params_get(libxl_ctx *ctx, uint32_t domid,
|
|
libxl_domain_sched_params *scinfo)
|
|
{
|
|
GC_INIT(ctx);
|
|
int ret;
|
|
|
|
libxl_domain_sched_params_init(scinfo);
|
|
|
|
scinfo->sched = libxl__domain_scheduler(gc, domid);
|
|
|
|
switch (scinfo->sched) {
|
|
case LIBXL_SCHEDULER_SEDF:
|
|
LOGD(ERROR, domid, "SEDF scheduler no longer available");
|
|
ret=ERROR_FEATURE_REMOVED;
|
|
break;
|
|
case LIBXL_SCHEDULER_CREDIT:
|
|
ret=sched_credit_domain_get(gc, domid, scinfo);
|
|
break;
|
|
case LIBXL_SCHEDULER_CREDIT2:
|
|
ret=sched_credit2_domain_get(gc, domid, scinfo);
|
|
break;
|
|
case LIBXL_SCHEDULER_RTDS:
|
|
ret=sched_rtds_domain_get(gc, domid, scinfo);
|
|
break;
|
|
case LIBXL_SCHEDULER_NULL:
|
|
ret=sched_null_domain_get(gc, domid, scinfo);
|
|
break;
|
|
default:
|
|
LOGD(ERROR, domid, "Unknown scheduler");
|
|
ret=ERROR_INVAL;
|
|
break;
|
|
}
|
|
|
|
GC_FREE;
|
|
return ret;
|
|
}
|
|
|
|
int libxl_vcpu_sched_params_get(libxl_ctx *ctx, uint32_t domid,
|
|
libxl_vcpu_sched_params *scinfo)
|
|
{
|
|
GC_INIT(ctx);
|
|
int rc;
|
|
|
|
scinfo->sched = libxl__domain_scheduler(gc, domid);
|
|
|
|
switch (scinfo->sched) {
|
|
case LIBXL_SCHEDULER_SEDF:
|
|
LOGD(ERROR, domid, "SEDF scheduler is no longer available");
|
|
rc = ERROR_FEATURE_REMOVED;
|
|
break;
|
|
case LIBXL_SCHEDULER_CREDIT:
|
|
case LIBXL_SCHEDULER_CREDIT2:
|
|
case LIBXL_SCHEDULER_ARINC653:
|
|
case LIBXL_SCHEDULER_NULL:
|
|
LOGD(ERROR, domid, "per-VCPU parameter getting not supported for this scheduler");
|
|
rc = ERROR_INVAL;
|
|
break;
|
|
case LIBXL_SCHEDULER_RTDS:
|
|
rc = sched_rtds_vcpu_get(gc, domid, scinfo);
|
|
break;
|
|
default:
|
|
LOGD(ERROR, domid, "Unknown scheduler");
|
|
rc = ERROR_INVAL;
|
|
break;
|
|
}
|
|
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
int libxl_vcpu_sched_params_get_all(libxl_ctx *ctx, uint32_t domid,
|
|
libxl_vcpu_sched_params *scinfo)
|
|
{
|
|
GC_INIT(ctx);
|
|
int rc;
|
|
|
|
scinfo->sched = libxl__domain_scheduler(gc, domid);
|
|
|
|
switch (scinfo->sched) {
|
|
case LIBXL_SCHEDULER_SEDF:
|
|
LOGD(ERROR, domid, "SEDF scheduler is no longer available");
|
|
rc = ERROR_FEATURE_REMOVED;
|
|
break;
|
|
case LIBXL_SCHEDULER_CREDIT:
|
|
case LIBXL_SCHEDULER_CREDIT2:
|
|
case LIBXL_SCHEDULER_ARINC653:
|
|
case LIBXL_SCHEDULER_NULL:
|
|
LOGD(ERROR, domid, "per-VCPU parameter getting not supported for this scheduler");
|
|
rc = ERROR_INVAL;
|
|
break;
|
|
case LIBXL_SCHEDULER_RTDS:
|
|
rc = sched_rtds_vcpu_get_all(gc, domid, scinfo);
|
|
break;
|
|
default:
|
|
LOGD(ERROR, domid, "Unknown scheduler");
|
|
rc = ERROR_INVAL;
|
|
break;
|
|
}
|
|
|
|
GC_FREE;
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* mode: C
|
|
* c-basic-offset: 4
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*/
|