From patchwork Wed Mar 16 16:47:48 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chong Li X-Patchwork-Id: 8602551 Return-Path: X-Original-To: patchwork-xen-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 037379F6E1 for ; Wed, 16 Mar 2016 16:50:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9C2D6202E6 for ; Wed, 16 Mar 2016 16:50:41 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2A81B2022A for ; Wed, 16 Mar 2016 16:50:40 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1agEc9-000282-NH; Wed, 16 Mar 2016 16:48:05 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1agEc8-00026a-OP for xen-devel@lists.xen.org; Wed, 16 Mar 2016 16:48:04 +0000 Received: from [85.158.139.211] by server-2.bemta-5.messagelabs.com id 01/A5-12342-44E89E65; Wed, 16 Mar 2016 16:48:04 +0000 X-Env-Sender: lichong659@gmail.com X-Msg-Ref: server-8.tower-206.messagelabs.com!1458146882!29258976!1 X-Originating-IP: [209.85.213.172] X-SpamReason: No, hits=0.3 required=7.0 tests=MAILTO_TO_SPAM_ADDR X-StarScan-Received: X-StarScan-Version: 8.11; banners=-,-,- X-VirusChecked: Checked Received: (qmail 47929 invoked from network); 16 Mar 2016 16:48:03 -0000 Received: from mail-ig0-f172.google.com (HELO mail-ig0-f172.google.com) (209.85.213.172) by server-8.tower-206.messagelabs.com with AES128-GCM-SHA256 encrypted SMTP; 16 Mar 2016 16:48:03 -0000 Received: by mail-ig0-f172.google.com with SMTP id mh10so49038361igb.0 for ; Wed, 16 Mar 2016 09:48:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=5Y+CruY5TeOQbJNoOdr0P9o2bZs2BDiHd41OM/Fxv3w=; b=rf26u7HuNI0ujUcB2jVrVEqSwRS6g9a2CtHadQz1AWgsINrH0zxIsTw5yJZtypOvO4 31XEsqsNIJK53NDPN+a5uaL6nFXUU1GJxGz4TsR5ZJ2vkSXVFSK9COrrqdoRbtUQ1szi LuvL96lxQskbGMQ2MeD/8/cNkyoVbN6HN/o183ZdxEfqSdphixbTVAmwUl3vU9X1gnM/ o6P4s+hMjml0IpH+1o+a0cV+Zffzj+TPRH2MFEX3IqcNXBxxAH29UXxYSU7b6JYF2sfz kgLyL728ZhLxD5MDU01rlgUrCIGMLyTFJ0Q4fdWGwaWGo6FS+GpOCGGrzoM9WQnTZ15D ojpQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=5Y+CruY5TeOQbJNoOdr0P9o2bZs2BDiHd41OM/Fxv3w=; b=NNh6oVCseLGS90Ex400CeKHiKEtoPlCpWjKsyuwAaWN8L1azU0AgjgrAtlcx6U4TZE BoozCGZZhvl34id4cgsdD9PmAdq7/mQBa1DEH8rtgwpae794FlumwzmXhWEAvUpiPstc gTkIRoewqgujCc5yb1nXzbQ+bHhs2oRf8nJ3+UsC+ZndYKOV+EH+OpL4xmns7e1xKLRf GkpKRi6/cY8TTIxxYzZttT/veVn6EKZ1Qr4odv713g7EPbSwSgi2laVRTmDLYwe80OFu tW7ga/cpY4dqB3iu8NyU77z2LvklOupArl/EFRwD0s1Z7RcZIEkHUlvLsNnkem+LZOBy lGbw== X-Gm-Message-State: AD7BkJJCCfiGXQxHR7f8XPe7WoqcwpxKzVLyyZWzsjbDvnmlnGwOV/LAOgbQGhfq7i1ELQ== X-Received: by 10.50.30.201 with SMTP id u9mr6300734igh.63.1458146881975; Wed, 16 Mar 2016 09:48:01 -0700 (PDT) Received: from chong-OptiPlex-960.seas.wustl.edu (admin998.cec.wustl.edu. [128.252.20.193]) by smtp.googlemail.com with ESMTPSA id p8sm6838976igi.2.2016.03.16.09.48.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 16 Mar 2016 09:48:00 -0700 (PDT) From: Chong Li To: xen-devel@lists.xen.org Date: Wed, 16 Mar 2016 11:47:48 -0500 Message-Id: <1458146871-2813-2-git-send-email-lichong659@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1458146871-2813-1-git-send-email-lichong659@gmail.com> References: <1458146871-2813-1-git-send-email-lichong659@gmail.com> Cc: Chong Li , Sisu Xi , george.dunlap@eu.citrix.com, dario.faggioli@citrix.com, Meng Xu , jbeulich@suse.com, lichong659@gmail.com, dgolomb@seas.upenn.edu Subject: [Xen-devel] [PATCH v7 for Xen 4.7 1/4] xen: enable per-VCPU parameter settings for RTDS scheduler X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add XEN_DOMCTL_SCHEDOP_getvcpuinfo and _putvcpuinfo hypercalls to independently get and set the scheduling parameters of each vCPU of a domain Signed-off-by: Chong Li Signed-off-by: Meng Xu Signed-off-by: Sisu Xi --- Changes on PATCH v6: 1) Add explain for nr_vcpus in struct xen_domctl_scheduler_op, because it is used in both IN and OUT ways. 2) Remove the check and warning for vcpu settings with low budget or budget. Making this feature "per-domain" or "per-operation" is one of the future work. 3) In the *cntl() functions in sched_credit.c and sched_credit2.c, change the "if-else" structure to "switch" structure. 4) In rt_dom_cntl(), use copy_to_guest* instead of __copy_to_guest*, because the latter one requires lock protection. Changes on PATCH v5: 1) When processing XEN_DOMCTL_SCHEDOP_get/putvcpuinfo, we do preemption check in a similar way to XEN_SYSCTL_pcitopoinfo Changes on PATCH v4: 1) Add uint32_t vcpu_index to struct xen_domctl_scheduler_op. When processing XEN_DOMCTL_SCHEDOP_get/putvcpuinfo, we call hypercall_preemption_check in case the current hypercall lasts too long. If we decide to preempt the current hypercall, we record the index of the most-recent finished vcpu into the vcpu_index of struct xen_domctl_scheduler_op. So when we resume the hypercall after preemption, we start processing from the posion specified by vcpu_index, and don't need to repeat the work that has already been done in the hypercall before the preemption. (This design is based on the do_grant_table_op() in grant_table.c) 2) Coding style changes Changes on PATCH v3: 1) Remove struct xen_domctl_schedparam_t. 2) Change struct xen_domctl_scheduler_op. 3) Check if period/budget is within a validated range Changes on PATCH v2: 1) Change struct xen_domctl_scheduler_op, for transferring per-vcpu parameters between libxc and hypervisor. 2) Handler of XEN_DOMCTL_SCHEDOP_getinfo now just returns the default budget and period values of RTDS scheduler. 3) Handler of XEN_DOMCTL_SCHEDOP_getvcpuinfo now can return a random subset of the parameters of the VCPUs of a specific domain CC: CC: CC: CC: CC: CC: --- xen/common/sched_credit.c | 17 ++++--- xen/common/sched_credit2.c | 16 ++++--- xen/common/sched_rt.c | 114 ++++++++++++++++++++++++++++++++++++++------ xen/common/schedule.c | 15 ++++-- xen/include/public/domctl.h | 63 +++++++++++++++++++----- 5 files changed, 183 insertions(+), 42 deletions(-) diff --git a/xen/common/sched_credit.c b/xen/common/sched_credit.c index 0dce790..82b0d14 100644 --- a/xen/common/sched_credit.c +++ b/xen/common/sched_credit.c @@ -1054,15 +1054,16 @@ csched_dom_cntl( * lock. Runq lock not needed anywhere in here. */ spin_lock_irqsave(&prv->lock, flags); - if ( op->cmd == XEN_DOMCTL_SCHEDOP_getinfo ) + switch ( op->cmd ) { + case XEN_DOMCTL_SCHEDOP_putvcpuinfo: + case XEN_DOMCTL_SCHEDOP_getvcpuinfo: + return -EINVAL; + case XEN_DOMCTL_SCHEDOP_getinfo: op->u.credit.weight = sdom->weight; op->u.credit.cap = sdom->cap; - } - else - { - ASSERT(op->cmd == XEN_DOMCTL_SCHEDOP_putinfo); - + break; + case XEN_DOMCTL_SCHEDOP_putinfo: if ( op->u.credit.weight != 0 ) { if ( !list_empty(&sdom->active_sdom_elem) ) @@ -1075,7 +1076,9 @@ csched_dom_cntl( if ( op->u.credit.cap != (uint16_t)~0U ) sdom->cap = op->u.credit.cap; - + break; + default: + return -EINVAL; } spin_unlock_irqrestore(&prv->lock, flags); diff --git a/xen/common/sched_credit2.c b/xen/common/sched_credit2.c index 3c49ffa..46d54bc 100644 --- a/xen/common/sched_credit2.c +++ b/xen/common/sched_credit2.c @@ -1421,14 +1421,15 @@ csched2_dom_cntl( * runq lock to update csvcs. */ spin_lock_irqsave(&prv->lock, flags); - if ( op->cmd == XEN_DOMCTL_SCHEDOP_getinfo ) + switch ( op->cmd ) { + case XEN_DOMCTL_SCHEDOP_putvcpuinfo: + case XEN_DOMCTL_SCHEDOP_getvcpuinfo: + return -EINVAL; + case XEN_DOMCTL_SCHEDOP_getinfo: op->u.credit2.weight = sdom->weight; - } - else - { - ASSERT(op->cmd == XEN_DOMCTL_SCHEDOP_putinfo); - + break; + case XEN_DOMCTL_SCHEDOP_putinfo: if ( op->u.credit2.weight != 0 ) { struct vcpu *v; @@ -1457,6 +1458,9 @@ csched2_dom_cntl( vcpu_schedule_unlock(lock, svc->vcpu); } } + break; + default: + return -EINVAL; } spin_unlock_irqrestore(&prv->lock, flags); diff --git a/xen/common/sched_rt.c b/xen/common/sched_rt.c index 3f1d047..359c2db 100644 --- a/xen/common/sched_rt.c +++ b/xen/common/sched_rt.c @@ -86,6 +86,22 @@ #define RTDS_DEFAULT_PERIOD (MICROSECS(10000)) #define RTDS_DEFAULT_BUDGET (MICROSECS(4000)) +/* + * Max period: max delta of time type, because period is added to the time + * a vcpu activates, so this must not overflow. + * Min period: 10 us, considering the scheduling overhead (when period is + * too low, scheduling is invoked too frequently, causing high overhead). + */ +#define RTDS_MAX_PERIOD (STIME_DELTA_MAX) +#define RTDS_MIN_PERIOD (MICROSECS(10)) + +/* + * Min budget: 10 us, considering the scheduling overhead (when budget is + * consumed too fast, scheduling is invoked too frequently, causing + * high overhead). + */ +#define RTDS_MIN_BUDGET (MICROSECS(10)) + #define UPDATE_LIMIT_SHIFT 10 #define MAX_SCHEDULE (MILLISECS(1)) /* @@ -1129,24 +1145,22 @@ rt_dom_cntl( struct vcpu *v; unsigned long flags; int rc = 0; + xen_domctl_schedparam_vcpu_t local_sched; + s_time_t period, budget; + uint32_t index = 0; switch ( op->cmd ) { case XEN_DOMCTL_SCHEDOP_getinfo: - if ( d->max_vcpus > 0 ) - { - spin_lock_irqsave(&prv->lock, flags); - svc = rt_vcpu(d->vcpu[0]); - op->u.rtds.period = svc->period / MICROSECS(1); - op->u.rtds.budget = svc->budget / MICROSECS(1); - spin_unlock_irqrestore(&prv->lock, flags); - } - else - { - /* If we don't have vcpus yet, let's just return the defaults. */ - op->u.rtds.period = RTDS_DEFAULT_PERIOD; - op->u.rtds.budget = RTDS_DEFAULT_BUDGET; - } + /* Return the default parameters. + * A previous bug fixed here: + * The default PERIOD or BUDGET should be divided by MICROSECS(1), + * before returned to upper caller. + */ + spin_lock_irqsave(&prv->lock, flags); + op->u.rtds.period = RTDS_DEFAULT_PERIOD / MICROSECS(1); + op->u.rtds.budget = RTDS_DEFAULT_BUDGET / MICROSECS(1); + spin_unlock_irqrestore(&prv->lock, flags); break; case XEN_DOMCTL_SCHEDOP_putinfo: if ( op->u.rtds.period == 0 || op->u.rtds.budget == 0 ) @@ -1163,6 +1177,78 @@ rt_dom_cntl( } spin_unlock_irqrestore(&prv->lock, flags); break; + case XEN_DOMCTL_SCHEDOP_getvcpuinfo: + while ( index < op->u.v.nr_vcpus ) + { + if ( copy_from_guest_offset(&local_sched, + op->u.v.vcpus, index, 1) ) + { + rc = -EFAULT; + break; + } + if ( local_sched.vcpuid >= d->max_vcpus || + d->vcpu[local_sched.vcpuid] == NULL ) + { + rc = -EINVAL; + break; + } + + spin_lock_irqsave(&prv->lock, flags); + svc = rt_vcpu(d->vcpu[local_sched.vcpuid]); + local_sched.u.rtds.budget = svc->budget / MICROSECS(1); + local_sched.u.rtds.period = svc->period / MICROSECS(1); + spin_unlock_irqrestore(&prv->lock, flags); + + if ( copy_to_guest_offset(op->u.v.vcpus, index, + &local_sched, 1) ) + { + rc = -EFAULT; + break; + } + if ( (++index > 0x3f) && hypercall_preempt_check() ) + break; + } + if ( !rc ) /* notify upper caller how many vcpus have been processed */ + op->u.v.nr_vcpus = index; + break; + + case XEN_DOMCTL_SCHEDOP_putvcpuinfo: + while ( index < op->u.v.nr_vcpus ) + { + if ( copy_from_guest_offset(&local_sched, + op->u.v.vcpus, index, 1) ) + { + rc = -EFAULT; + break; + } + if ( local_sched.vcpuid >= d->max_vcpus || + d->vcpu[local_sched.vcpuid] == NULL ) + { + rc = -EINVAL; + break; + } + + period = MICROSECS(local_sched.u.rtds.period); + budget = MICROSECS(local_sched.u.rtds.budget); + if ( period > RTDS_MAX_PERIOD || budget < RTDS_MIN_BUDGET || + budget > period || period < RTDS_MIN_PERIOD ) + { + rc = -EINVAL; + break; + } + + spin_lock_irqsave(&prv->lock, flags); + svc = rt_vcpu(d->vcpu[local_sched.vcpuid]); + svc->period = period; + svc->budget = budget; + spin_unlock_irqrestore(&prv->lock, flags); + + if ( (++index > 0x3f) && hypercall_preempt_check() ) + break; + } + if ( !rc ) /* notify upper caller how many vcpus have been processed */ + op->u.v.nr_vcpus = index; + break; } return rc; diff --git a/xen/common/schedule.c b/xen/common/schedule.c index c195129..cd25e08 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -1148,11 +1148,20 @@ long sched_adjust(struct domain *d, struct xen_domctl_scheduler_op *op) if ( ret ) return ret; - if ( (op->sched_id != DOM2OP(d)->sched_id) || - ((op->cmd != XEN_DOMCTL_SCHEDOP_putinfo) && - (op->cmd != XEN_DOMCTL_SCHEDOP_getinfo)) ) + if ( op->sched_id != DOM2OP(d)->sched_id ) return -EINVAL; + switch ( op->cmd ) + { + case XEN_DOMCTL_SCHEDOP_putinfo: + case XEN_DOMCTL_SCHEDOP_getinfo: + case XEN_DOMCTL_SCHEDOP_putvcpuinfo: + case XEN_DOMCTL_SCHEDOP_getvcpuinfo: + break; + default: + return -EINVAL; + } + /* NB: the pluggable scheduler code needs to take care * of locking by itself. */ if ( (ret = SCHED_OP(DOM2OP(d), adjust, d, op)) == 0 ) diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 7a56b3f..9297c01 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -338,24 +338,63 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_vcpus_t); #define XEN_SCHEDULER_ARINC653 7 #define XEN_SCHEDULER_RTDS 8 -/* Set or get info? */ +typedef struct xen_domctl_sched_credit { + uint16_t weight; + uint16_t cap; +} xen_domctl_sched_credit_t; + +typedef struct xen_domctl_sched_credit2 { + uint16_t weight; +} xen_domctl_sched_credit2_t; + +typedef struct xen_domctl_sched_rtds { + uint32_t period; + uint32_t budget; +} xen_domctl_sched_rtds_t; + +typedef struct xen_domctl_schedparam_vcpu { + union { + xen_domctl_sched_credit_t credit; + xen_domctl_sched_credit2_t credit2; + xen_domctl_sched_rtds_t rtds; + } u; + uint32_t vcpuid; + uint16_t padding[2]; +} xen_domctl_schedparam_vcpu_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_schedparam_vcpu_t); + +/* + * Set or get info? + * For schedulers supporting per-vcpu settings (e.g., RTDS): + * XEN_DOMCTL_SCHEDOP_putinfo sets params for all vcpus; + * XEN_DOMCTL_SCHEDOP_getinfo gets default params; + * XEN_DOMCTL_SCHEDOP_put(get)vcpuinfo sets (gets) params of vcpus; + * + * For schedulers not supporting per-vcpu settings: + * XEN_DOMCTL_SCHEDOP_putinfo sets params for all vcpus; + * XEN_DOMCTL_SCHEDOP_getinfo gets domain-wise params; + * XEN_DOMCTL_SCHEDOP_put(get)vcpuinfo returns error; + */ #define XEN_DOMCTL_SCHEDOP_putinfo 0 #define XEN_DOMCTL_SCHEDOP_getinfo 1 +#define XEN_DOMCTL_SCHEDOP_putvcpuinfo 2 +#define XEN_DOMCTL_SCHEDOP_getvcpuinfo 3 struct xen_domctl_scheduler_op { uint32_t sched_id; /* XEN_SCHEDULER_* */ uint32_t cmd; /* XEN_DOMCTL_SCHEDOP_* */ union { - struct xen_domctl_sched_credit { - uint16_t weight; - uint16_t cap; - } credit; - struct xen_domctl_sched_credit2 { - uint16_t weight; - } credit2; - struct xen_domctl_sched_rtds { - uint32_t period; - uint32_t budget; - } rtds; + xen_domctl_sched_credit_t credit; + xen_domctl_sched_credit2_t credit2; + xen_domctl_sched_rtds_t rtds; + struct { + XEN_GUEST_HANDLE_64(xen_domctl_schedparam_vcpu_t) vcpus; + /* + * IN: Number of elements in vcpus array. + * OUT: Number of processed elements of vcpus array. + */ + uint32_t nr_vcpus; + uint32_t padding; + } v; } u; }; typedef struct xen_domctl_scheduler_op xen_domctl_scheduler_op_t;