@@ -23,6 +23,7 @@
#include <xen/event.h>
#include <xen/guest_access.h>
#include <xen/iocap.h>
+#include <xen/sched.h>
#include <xen/spinlock.h>
#include <xen/trace.h>
@@ -22,6 +22,7 @@
#include <xen/event.h>
#include <xen/hypercall.h>
#include <xen/lib.h>
+#include <xen/sched.h>
#include <xen/trace.h>
#include <xen/softirq.h>
@@ -155,8 +156,8 @@ static void nmi_mce_softirq(void)
* Set the tmp value unconditionally, so that the check in the iret
* hypercall works.
*/
- cpumask_copy(st->vcpu->cpu_hard_affinity_tmp,
- st->vcpu->cpu_hard_affinity);
+ cpumask_copy(st->vcpu->sched_unit->cpu_hard_affinity_tmp,
+ st->vcpu->sched_unit->cpu_hard_affinity);
if ( (cpu != st->processor) ||
(st->processor != st->vcpu->processor) )
@@ -1594,16 +1594,17 @@ static void pci_serr_softirq(void)
void async_exception_cleanup(struct vcpu *curr)
{
int trap;
+ struct sched_unit *unit = curr->sched_unit;
if ( !curr->async_exception_mask )
return;
/* Restore affinity. */
- if ( !cpumask_empty(curr->cpu_hard_affinity_tmp) &&
- !cpumask_equal(curr->cpu_hard_affinity_tmp, curr->cpu_hard_affinity) )
+ if ( !cpumask_empty(unit->cpu_hard_affinity_tmp) &&
+ !cpumask_equal(unit->cpu_hard_affinity_tmp, unit->cpu_hard_affinity) )
{
- vcpu_set_hard_affinity(curr, curr->cpu_hard_affinity_tmp);
- cpumask_clear(curr->cpu_hard_affinity_tmp);
+ vcpu_set_hard_affinity(curr, unit->cpu_hard_affinity_tmp);
+ cpumask_clear(unit->cpu_hard_affinity_tmp);
}
if ( !(curr->async_exception_mask & (curr->async_exception_mask - 1)) )
@@ -125,11 +125,6 @@ static void vcpu_info_reset(struct vcpu *v)
static void vcpu_destroy(struct vcpu *v)
{
- free_cpumask_var(v->cpu_hard_affinity);
- free_cpumask_var(v->cpu_hard_affinity_tmp);
- free_cpumask_var(v->cpu_hard_affinity_saved);
- free_cpumask_var(v->cpu_soft_affinity);
-
free_vcpu_struct(v);
}
@@ -153,12 +148,6 @@ struct vcpu *vcpu_create(
grant_table_init_vcpu(v);
- if ( !zalloc_cpumask_var(&v->cpu_hard_affinity) ||
- !zalloc_cpumask_var(&v->cpu_hard_affinity_tmp) ||
- !zalloc_cpumask_var(&v->cpu_hard_affinity_saved) ||
- !zalloc_cpumask_var(&v->cpu_soft_affinity) )
- goto fail;
-
if ( is_idle_domain(d) )
{
v->runstate.state = RUNSTATE_running;
@@ -198,7 +187,6 @@ struct vcpu *vcpu_create(
sched_destroy_vcpu(v);
fail_wq:
destroy_waitqueue_vcpu(v);
- fail:
vcpu_destroy(v);
return NULL;
@@ -557,9 +545,10 @@ void domain_update_node_affinity(struct domain *d)
*/
for_each_vcpu ( d, v )
{
- cpumask_or(dom_cpumask, dom_cpumask, v->cpu_hard_affinity);
+ cpumask_or(dom_cpumask, dom_cpumask,
+ v->sched_unit->cpu_hard_affinity);
cpumask_or(dom_cpumask_soft, dom_cpumask_soft,
- v->cpu_soft_affinity);
+ v->sched_unit->cpu_soft_affinity);
}
/* Filter out non-online cpus */
cpumask_and(dom_cpumask, dom_cpumask, online);
@@ -1226,7 +1215,7 @@ int vcpu_reset(struct vcpu *v)
v->async_exception_mask = 0;
memset(v->async_exception_state, 0, sizeof(v->async_exception_state));
#endif
- cpumask_clear(v->cpu_hard_affinity_tmp);
+ cpumask_clear(v->sched_unit->cpu_hard_affinity_tmp);
clear_bit(_VPF_blocked, &v->pause_flags);
clear_bit(_VPF_in_reset, &v->pause_flags);
@@ -614,6 +614,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
case XEN_DOMCTL_getvcpuaffinity:
{
struct vcpu *v;
+ struct sched_unit *unit;
struct xen_domctl_vcpuaffinity *vcpuaff = &op->u.vcpuaffinity;
ret = -EINVAL;
@@ -624,6 +625,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
if ( (v = d->vcpu[vcpuaff->vcpu]) == NULL )
break;
+ unit = v->sched_unit;
ret = -EINVAL;
if ( vcpuaffinity_params_invalid(vcpuaff) )
break;
@@ -643,7 +645,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
ret = -ENOMEM;
break;
}
- cpumask_copy(old_affinity, v->cpu_hard_affinity);
+ cpumask_copy(old_affinity, unit->cpu_hard_affinity);
if ( !alloc_cpumask_var(&new_affinity) )
{
@@ -676,7 +678,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
* For hard affinity, what we return is the intersection of
* cpupool's online mask and the new hard affinity.
*/
- cpumask_and(new_affinity, online, v->cpu_hard_affinity);
+ cpumask_and(new_affinity, online, unit->cpu_hard_affinity);
ret = cpumask_to_xenctl_bitmap(&vcpuaff->cpumap_hard,
new_affinity);
}
@@ -705,7 +707,8 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
* hard affinity.
*/
cpumask_and(new_affinity, new_affinity, online);
- cpumask_and(new_affinity, new_affinity, v->cpu_hard_affinity);
+ cpumask_and(new_affinity, new_affinity,
+ unit->cpu_hard_affinity);
ret = cpumask_to_xenctl_bitmap(&vcpuaff->cpumap_soft,
new_affinity);
}
@@ -718,10 +721,10 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
{
if ( vcpuaff->flags & XEN_VCPUAFFINITY_HARD )
ret = cpumask_to_xenctl_bitmap(&vcpuaff->cpumap_hard,
- v->cpu_hard_affinity);
+ unit->cpu_hard_affinity);
if ( vcpuaff->flags & XEN_VCPUAFFINITY_SOFT )
ret = cpumask_to_xenctl_bitmap(&vcpuaff->cpumap_soft,
- v->cpu_soft_affinity);
+ unit->cpu_soft_affinity);
}
break;
}
@@ -312,8 +312,8 @@ static void dump_domains(unsigned char key)
printk("dirty_cpu=%u", v->dirty_cpu);
printk("\n");
printk(" cpu_hard_affinity={%*pbl} cpu_soft_affinity={%*pbl}\n",
- nr_cpu_ids, cpumask_bits(v->cpu_hard_affinity),
- nr_cpu_ids, cpumask_bits(v->cpu_soft_affinity));
+ nr_cpu_ids, cpumask_bits(v->sched_unit->cpu_hard_affinity),
+ nr_cpu_ids, cpumask_bits(v->sched_unit->cpu_soft_affinity));
printk(" pause_count=%d pause_flags=%lx\n",
atomic_read(&v->pause_count), v->pause_flags);
arch_dump_vcpu_info(v);
@@ -350,6 +350,7 @@ DEFINE_PER_CPU(unsigned int, last_tickle_cpu);
static inline void __runq_tickle(struct csched_unit *new)
{
unsigned int cpu = new->vcpu->processor;
+ struct sched_unit *unit = new->vcpu->sched_unit;
struct csched_unit * const cur = CSCHED_UNIT(curr_on_cpu(cpu));
struct csched_private *prv = CSCHED_PRIV(per_cpu(scheduler, cpu));
cpumask_t mask, idle_mask, *online;
@@ -375,7 +376,7 @@ static inline void __runq_tickle(struct csched_unit *new)
if ( unlikely(test_bit(CSCHED_FLAG_VCPU_PINNED, &new->flags) &&
cpumask_test_cpu(cpu, &idle_mask)) )
{
- ASSERT(cpumask_cycle(cpu, new->vcpu->cpu_hard_affinity) == cpu);
+ ASSERT(cpumask_cycle(cpu, unit->cpu_hard_affinity) == cpu);
SCHED_STAT_CRANK(tickled_idle_cpu_excl);
__cpumask_set_cpu(cpu, &mask);
goto tickle;
@@ -410,11 +411,11 @@ static inline void __runq_tickle(struct csched_unit *new)
int new_idlers_empty;
if ( balance_step == BALANCE_SOFT_AFFINITY
- && !has_soft_affinity(new->vcpu) )
+ && !has_soft_affinity(unit) )
continue;
/* Are there idlers suitable for new (for this balance step)? */
- affinity_balance_cpumask(new->vcpu, balance_step,
+ affinity_balance_cpumask(unit, balance_step,
cpumask_scratch_cpu(cpu));
cpumask_and(cpumask_scratch_cpu(cpu),
cpumask_scratch_cpu(cpu), &idle_mask);
@@ -443,8 +444,7 @@ static inline void __runq_tickle(struct csched_unit *new)
*/
if ( new_idlers_empty && new->pri > cur->pri )
{
- if ( cpumask_intersects(cur->vcpu->cpu_hard_affinity,
- &idle_mask) )
+ if ( cpumask_intersects(unit->cpu_hard_affinity, &idle_mask) )
{
SCHED_VCPU_STAT_CRANK(cur, kicked_away);
SCHED_VCPU_STAT_CRANK(cur, migrate_r);
@@ -695,7 +695,7 @@ static inline bool
__csched_vcpu_is_cache_hot(const struct csched_private *prv, struct vcpu *v)
{
bool hot = prv->vcpu_migr_delay &&
- (NOW() - v->last_run_time) < prv->vcpu_migr_delay;
+ (NOW() - v->sched_unit->last_run_time) < prv->vcpu_migr_delay;
if ( hot )
SCHED_STAT_CRANK(vcpu_hot);
@@ -733,7 +733,7 @@ _csched_cpu_pick(const struct scheduler *ops, struct vcpu *vc, bool_t commit)
for_each_affinity_balance_step( balance_step )
{
- affinity_balance_cpumask(vc, balance_step, cpus);
+ affinity_balance_cpumask(vc->sched_unit, balance_step, cpus);
cpumask_and(cpus, online, cpus);
/*
* We want to pick up a pcpu among the ones that are online and
@@ -752,7 +752,7 @@ _csched_cpu_pick(const struct scheduler *ops, struct vcpu *vc, bool_t commit)
* balancing step all together.
*/
if ( balance_step == BALANCE_SOFT_AFFINITY &&
- (!has_soft_affinity(vc) || cpumask_empty(cpus)) )
+ (!has_soft_affinity(vc->sched_unit) || cpumask_empty(cpus)) )
continue;
/* If present, prefer vc's current processor */
@@ -1652,10 +1652,10 @@ csched_runq_steal(int peer_cpu, int cpu, int pri, int balance_step)
* or counter.
*/
if ( vc->is_running || (balance_step == BALANCE_SOFT_AFFINITY &&
- !has_soft_affinity(vc)) )
+ !has_soft_affinity(vc->sched_unit)) )
continue;
- affinity_balance_cpumask(vc, balance_step, cpumask_scratch);
+ affinity_balance_cpumask(vc->sched_unit, balance_step, cpumask_scratch);
if ( __csched_vcpu_is_migrateable(prv, vc, cpu, cpumask_scratch) )
{
/* We got a candidate. Grab it! */
@@ -699,10 +699,10 @@ static int get_fallback_cpu(struct csched2_unit *svc)
{
int cpu = v->processor;
- if ( bs == BALANCE_SOFT_AFFINITY && !has_soft_affinity(v) )
+ if ( bs == BALANCE_SOFT_AFFINITY && !has_soft_affinity(v->sched_unit) )
continue;
- affinity_balance_cpumask(v, bs, cpumask_scratch_cpu(cpu));
+ affinity_balance_cpumask(v->sched_unit, bs, cpumask_scratch_cpu(cpu));
cpumask_and(cpumask_scratch_cpu(cpu), cpumask_scratch_cpu(cpu),
cpupool_domain_cpumask(v->domain));
@@ -1390,10 +1390,10 @@ static s_time_t tickle_score(const struct scheduler *ops, s_time_t now,
*/
if ( score > 0 )
{
- if ( cpumask_test_cpu(cpu, new->vcpu->cpu_soft_affinity) )
+ if ( cpumask_test_cpu(cpu, new->vcpu->sched_unit->cpu_soft_affinity) )
score += CSCHED2_CREDIT_INIT;
- if ( !cpumask_test_cpu(cpu, cur->vcpu->cpu_soft_affinity) )
+ if ( !cpumask_test_cpu(cpu, cur->vcpu->sched_unit->cpu_soft_affinity) )
score += CSCHED2_CREDIT_INIT;
}
@@ -1436,6 +1436,7 @@ runq_tickle(const struct scheduler *ops, struct csched2_unit *new, s_time_t now)
{
int i, ipid = -1;
s_time_t max = 0;
+ struct sched_unit *unit = new->vcpu->sched_unit;
unsigned int bs, cpu = new->vcpu->processor;
struct csched2_runqueue_data *rqd = c2rqd(ops, cpu);
cpumask_t *online = cpupool_domain_cpumask(new->vcpu->domain);
@@ -1473,7 +1474,7 @@ runq_tickle(const struct scheduler *ops, struct csched2_unit *new, s_time_t now)
cpumask_test_cpu(cpu, &rqd->idle) &&
!cpumask_test_cpu(cpu, &rqd->tickled)) )
{
- ASSERT(cpumask_cycle(cpu, new->vcpu->cpu_hard_affinity) == cpu);
+ ASSERT(cpumask_cycle(cpu, unit->cpu_hard_affinity) == cpu);
SCHED_STAT_CRANK(tickled_idle_cpu_excl);
ipid = cpu;
goto tickle;
@@ -1482,10 +1483,10 @@ runq_tickle(const struct scheduler *ops, struct csched2_unit *new, s_time_t now)
for_each_affinity_balance_step( bs )
{
/* Just skip first step, if we don't have a soft affinity */
- if ( bs == BALANCE_SOFT_AFFINITY && !has_soft_affinity(new->vcpu) )
+ if ( bs == BALANCE_SOFT_AFFINITY && !has_soft_affinity(unit) )
continue;
- affinity_balance_cpumask(new->vcpu, bs, cpumask_scratch_cpu(cpu));
+ affinity_balance_cpumask(unit, bs, cpumask_scratch_cpu(cpu));
/*
* First of all, consider idle cpus, checking if we can just
@@ -1557,7 +1558,7 @@ runq_tickle(const struct scheduler *ops, struct csched2_unit *new, s_time_t now)
ipid = cpu;
/* If this is in new's soft affinity, just take it */
- if ( cpumask_test_cpu(cpu, new->vcpu->cpu_soft_affinity) )
+ if ( cpumask_test_cpu(cpu, unit->cpu_soft_affinity) )
{
SCHED_STAT_CRANK(tickled_busy_cpu);
goto tickle;
@@ -2243,7 +2244,7 @@ csched2_res_pick(const struct scheduler *ops, struct sched_unit *unit)
goto out;
}
- cpumask_and(cpumask_scratch_cpu(cpu), vc->cpu_hard_affinity,
+ cpumask_and(cpumask_scratch_cpu(cpu), unit->cpu_hard_affinity,
cpupool_domain_cpumask(vc->domain));
/*
@@ -2288,7 +2289,7 @@ csched2_res_pick(const struct scheduler *ops, struct sched_unit *unit)
*
* Find both runqueues in one pass.
*/
- has_soft = has_soft_affinity(vc);
+ has_soft = has_soft_affinity(unit);
for_each_cpu(i, &prv->active_queues)
{
struct csched2_runqueue_data *rqd;
@@ -2335,7 +2336,7 @@ csched2_res_pick(const struct scheduler *ops, struct sched_unit *unit)
cpumask_t mask;
cpumask_and(&mask, cpumask_scratch_cpu(cpu), &rqd->active);
- if ( cpumask_intersects(&mask, svc->vcpu->cpu_soft_affinity) )
+ if ( cpumask_intersects(&mask, unit->cpu_soft_affinity) )
{
min_s_avgload = rqd_avgload;
min_s_rqi = i;
@@ -2357,9 +2358,9 @@ csched2_res_pick(const struct scheduler *ops, struct sched_unit *unit)
* Note that, to obtain the soft-affinity mask, we "just" put what we
* have in cpumask_scratch in && with vc->cpu_soft_affinity. This is
* ok because:
- * - we know that vc->cpu_hard_affinity and vc->cpu_soft_affinity have
+ * - we know that unit->cpu_hard_affinity and ->cpu_soft_affinity have
* a non-empty intersection (because has_soft is true);
- * - we have vc->cpu_hard_affinity & cpupool_domain_cpumask() already
+ * - we have unit->cpu_hard_affinity & cpupool_domain_cpumask() already
* in cpumask_scratch, we do save a lot doing like this.
*
* It's kind of like open coding affinity_balance_cpumask() but, in
@@ -2367,7 +2368,7 @@ csched2_res_pick(const struct scheduler *ops, struct sched_unit *unit)
* cpumask operations.
*/
cpumask_and(cpumask_scratch_cpu(cpu), cpumask_scratch_cpu(cpu),
- vc->cpu_soft_affinity);
+ unit->cpu_soft_affinity);
cpumask_and(cpumask_scratch_cpu(cpu), cpumask_scratch_cpu(cpu),
&prv->rqd[min_s_rqi].active);
}
@@ -2475,6 +2476,7 @@ static void migrate(const struct scheduler *ops,
s_time_t now)
{
int cpu = svc->vcpu->processor;
+ struct sched_unit *unit = svc->vcpu->sched_unit;
if ( unlikely(tb_init_done) )
{
@@ -2512,7 +2514,7 @@ static void migrate(const struct scheduler *ops,
}
_runq_deassign(svc);
- cpumask_and(cpumask_scratch_cpu(cpu), svc->vcpu->cpu_hard_affinity,
+ cpumask_and(cpumask_scratch_cpu(cpu), unit->cpu_hard_affinity,
cpupool_domain_cpumask(svc->vcpu->domain));
cpumask_and(cpumask_scratch_cpu(cpu), cpumask_scratch_cpu(cpu),
&trqd->active);
@@ -2546,7 +2548,7 @@ static bool vcpu_is_migrateable(struct csched2_unit *svc,
struct vcpu *v = svc->vcpu;
int cpu = svc->vcpu->processor;
- cpumask_and(cpumask_scratch_cpu(cpu), v->cpu_hard_affinity,
+ cpumask_and(cpumask_scratch_cpu(cpu), v->sched_unit->cpu_hard_affinity,
cpupool_domain_cpumask(v->domain));
return !(svc->flags & CSFLAG_runq_migrate_request) &&
@@ -2780,7 +2782,7 @@ csched2_unit_migrate(
/* If here, new_cpu must be a valid Credit2 pCPU, and in our affinity. */
ASSERT(cpumask_test_cpu(new_cpu, &csched2_priv(ops)->initialized));
- ASSERT(cpumask_test_cpu(new_cpu, vc->cpu_hard_affinity));
+ ASSERT(cpumask_test_cpu(new_cpu, unit->cpu_hard_affinity));
trqd = c2rqd(ops, new_cpu);
@@ -3320,9 +3322,9 @@ runq_candidate(struct csched2_runqueue_data *rqd,
}
/* If scurr has a soft-affinity, let's check whether cpu is part of it */
- if ( has_soft_affinity(scurr->vcpu) )
+ if ( has_soft_affinity(scurr->vcpu->sched_unit) )
{
- affinity_balance_cpumask(scurr->vcpu, BALANCE_SOFT_AFFINITY,
+ affinity_balance_cpumask(scurr->vcpu->sched_unit, BALANCE_SOFT_AFFINITY,
cpumask_scratch);
if ( unlikely(!cpumask_test_cpu(cpu, cpumask_scratch)) )
{
@@ -3377,7 +3379,7 @@ runq_candidate(struct csched2_runqueue_data *rqd,
}
/* Only consider vcpus that are allowed to run on this processor. */
- if ( !cpumask_test_cpu(cpu, svc->vcpu->cpu_hard_affinity) )
+ if ( !cpumask_test_cpu(cpu, svc->vcpu->sched_unit->cpu_hard_affinity) )
{
(*skipped)++;
continue;
@@ -123,7 +123,8 @@ static inline struct null_unit *null_unit(const struct sched_unit *unit)
static inline bool vcpu_check_affinity(struct vcpu *v, unsigned int cpu,
unsigned int balance_step)
{
- affinity_balance_cpumask(v, balance_step, cpumask_scratch_cpu(cpu));
+ affinity_balance_cpumask(v->sched_unit, balance_step,
+ cpumask_scratch_cpu(cpu));
cpumask_and(cpumask_scratch_cpu(cpu), cpumask_scratch_cpu(cpu),
cpupool_domain_cpumask(v->domain));
@@ -281,10 +282,10 @@ pick_res(struct null_private *prv, struct sched_unit *unit)
for_each_affinity_balance_step( bs )
{
- if ( bs == BALANCE_SOFT_AFFINITY && !has_soft_affinity(v) )
+ if ( bs == BALANCE_SOFT_AFFINITY && !has_soft_affinity(unit) )
continue;
- affinity_balance_cpumask(v, bs, cpumask_scratch_cpu(cpu));
+ affinity_balance_cpumask(unit, bs, cpumask_scratch_cpu(cpu));
cpumask_and(cpumask_scratch_cpu(cpu), cpumask_scratch_cpu(cpu), cpus);
/*
@@ -321,7 +322,7 @@ pick_res(struct null_private *prv, struct sched_unit *unit)
* as we will actually assign the vCPU to the pCPU we return from here,
* only if the pCPU is free.
*/
- cpumask_and(cpumask_scratch_cpu(cpu), cpus, v->cpu_hard_affinity);
+ cpumask_and(cpumask_scratch_cpu(cpu), cpus, unit->cpu_hard_affinity);
new_cpu = cpumask_any(cpumask_scratch_cpu(cpu));
out:
@@ -430,7 +431,7 @@ static void null_unit_insert(const struct scheduler *ops,
lock = unit_schedule_lock(unit);
- cpumask_and(cpumask_scratch_cpu(cpu), v->cpu_hard_affinity,
+ cpumask_and(cpumask_scratch_cpu(cpu), unit->cpu_hard_affinity,
cpupool_domain_cpumask(v->domain));
/* If the pCPU is free, we assign v to it */
@@ -488,7 +489,8 @@ static void _vcpu_remove(struct null_private *prv, struct vcpu *v)
{
list_for_each_entry( wvc, &prv->waitq, waitq_elem )
{
- if ( bs == BALANCE_SOFT_AFFINITY && !has_soft_affinity(wvc->vcpu) )
+ if ( bs == BALANCE_SOFT_AFFINITY &&
+ !has_soft_affinity(wvc->vcpu->sched_unit) )
continue;
if ( vcpu_check_affinity(wvc->vcpu, cpu, bs) )
@@ -767,7 +769,7 @@ static struct task_slice null_schedule(const struct scheduler *ops,
list_for_each_entry( wvc, &prv->waitq, waitq_elem )
{
if ( bs == BALANCE_SOFT_AFFINITY &&
- !has_soft_affinity(wvc->vcpu) )
+ !has_soft_affinity(wvc->vcpu->sched_unit) )
continue;
if ( vcpu_check_affinity(wvc->vcpu, cpu, bs) )
@@ -327,7 +327,7 @@ rt_dump_vcpu(const struct scheduler *ops, const struct rt_unit *svc)
mask = cpumask_scratch_cpu(svc->vcpu->processor);
cpupool_mask = cpupool_domain_cpumask(svc->vcpu->domain);
- cpumask_and(mask, cpupool_mask, svc->vcpu->cpu_hard_affinity);
+ cpumask_and(mask, cpupool_mask, svc->vcpu->sched_unit->cpu_hard_affinity);
printk("[%5d.%-2u] cpu %u, (%"PRI_stime", %"PRI_stime"),"
" cur_b=%"PRI_stime" cur_d=%"PRI_stime" last_start=%"PRI_stime"\n"
" \t\t priority_level=%d has_extratime=%d\n"
@@ -645,7 +645,7 @@ rt_res_pick(const struct scheduler *ops, struct sched_unit *unit)
int cpu;
online = cpupool_domain_cpumask(vc->domain);
- cpumask_and(&cpus, online, vc->cpu_hard_affinity);
+ cpumask_and(&cpus, online, unit->cpu_hard_affinity);
cpu = cpumask_test_cpu(vc->processor, &cpus)
? vc->processor
@@ -1023,7 +1023,8 @@ runq_pick(const struct scheduler *ops, const cpumask_t *mask)
/* mask cpu_hard_affinity & cpupool & mask */
online = cpupool_domain_cpumask(iter_svc->vcpu->domain);
- cpumask_and(&cpu_common, online, iter_svc->vcpu->cpu_hard_affinity);
+ cpumask_and(&cpu_common, online,
+ iter_svc->vcpu->sched_unit->cpu_hard_affinity);
cpumask_and(&cpu_common, mask, &cpu_common);
if ( cpumask_empty(&cpu_common) )
continue;
@@ -1192,7 +1193,7 @@ runq_tickle(const struct scheduler *ops, struct rt_unit *new)
return;
online = cpupool_domain_cpumask(new->vcpu->domain);
- cpumask_and(¬_tickled, online, new->vcpu->cpu_hard_affinity);
+ cpumask_and(¬_tickled, online, new->vcpu->sched_unit->cpu_hard_affinity);
cpumask_andnot(¬_tickled, ¬_tickled, &prv->tickled);
/*
@@ -270,6 +270,12 @@ static void sched_free_unit(struct sched_unit *unit)
}
unit->vcpu->sched_unit = NULL;
+
+ free_cpumask_var(unit->cpu_hard_affinity);
+ free_cpumask_var(unit->cpu_hard_affinity_tmp);
+ free_cpumask_var(unit->cpu_hard_affinity_saved);
+ free_cpumask_var(unit->cpu_soft_affinity);
+
xfree(unit);
}
@@ -293,7 +299,17 @@ static struct sched_unit *sched_alloc_unit(struct vcpu *v)
unit->next_in_list = *prev_unit;
*prev_unit = unit;
+ if ( !zalloc_cpumask_var(&unit->cpu_hard_affinity) ||
+ !zalloc_cpumask_var(&unit->cpu_hard_affinity_tmp) ||
+ !zalloc_cpumask_var(&unit->cpu_hard_affinity_saved) ||
+ !zalloc_cpumask_var(&unit->cpu_soft_affinity) )
+ goto fail;
+
return unit;
+
+ fail:
+ sched_free_unit(unit);
+ return NULL;
}
int sched_init_vcpu(struct vcpu *v, unsigned int processor)
@@ -363,7 +379,7 @@ int sched_move_domain(struct domain *d, struct cpupool *c)
for_each_vcpu ( d, v )
{
- if ( v->affinity_broken )
+ if ( v->sched_unit->affinity_broken )
return -EBUSY;
}
@@ -682,7 +698,7 @@ static void vcpu_migrate_finish(struct vcpu *v)
*/
if ( pick_called &&
(new_lock == get_sched_res(new_cpu)->schedule_lock) &&
- cpumask_test_cpu(new_cpu, v->cpu_hard_affinity) &&
+ cpumask_test_cpu(new_cpu, v->sched_unit->cpu_hard_affinity) &&
cpumask_test_cpu(new_cpu, v->domain->cpupool->cpu_valid) )
break;
@@ -758,6 +774,7 @@ void restore_vcpu_affinity(struct domain *d)
{
spinlock_t *lock;
unsigned int old_cpu = v->processor;
+ struct sched_unit *unit = v->sched_unit;
ASSERT(!vcpu_runnable(v));
@@ -769,15 +786,15 @@ void restore_vcpu_affinity(struct domain *d)
* set v->processor of each of their vCPUs to something that will
* make sense for the scheduler of the cpupool in which they are in.
*/
- cpumask_and(cpumask_scratch_cpu(cpu), v->cpu_hard_affinity,
+ cpumask_and(cpumask_scratch_cpu(cpu), unit->cpu_hard_affinity,
cpupool_domain_cpumask(d));
if ( cpumask_empty(cpumask_scratch_cpu(cpu)) )
{
- if ( v->affinity_broken )
+ if ( unit->affinity_broken )
{
- sched_set_affinity(v, v->cpu_hard_affinity_saved, NULL);
- v->affinity_broken = 0;
- cpumask_and(cpumask_scratch_cpu(cpu), v->cpu_hard_affinity,
+ sched_set_affinity(v, unit->cpu_hard_affinity_saved, NULL);
+ unit->affinity_broken = 0;
+ cpumask_and(cpumask_scratch_cpu(cpu), unit->cpu_hard_affinity,
cpupool_domain_cpumask(d));
}
@@ -785,18 +802,17 @@ void restore_vcpu_affinity(struct domain *d)
{
printk(XENLOG_DEBUG "Breaking affinity for %pv\n", v);
sched_set_affinity(v, &cpumask_all, NULL);
- cpumask_and(cpumask_scratch_cpu(cpu), v->cpu_hard_affinity,
+ cpumask_and(cpumask_scratch_cpu(cpu), unit->cpu_hard_affinity,
cpupool_domain_cpumask(d));
}
}
v->processor = cpumask_any(cpumask_scratch_cpu(cpu));
- v->sched_unit->res = get_sched_res(v->processor);
+ unit->res = get_sched_res(v->processor);
- lock = unit_schedule_lock_irq(v->sched_unit);
- v->sched_unit->res = sched_pick_resource(vcpu_scheduler(v),
- v->sched_unit);
- v->processor = v->sched_unit->res->processor;
+ lock = unit_schedule_lock_irq(unit);
+ unit->res = sched_pick_resource(vcpu_scheduler(v), unit);
+ v->processor = unit->res->processor;
spin_unlock_irq(lock);
if ( old_cpu != v->processor )
@@ -828,16 +844,17 @@ int cpu_disable_scheduler(unsigned int cpu)
for_each_vcpu ( d, v )
{
unsigned long flags;
- spinlock_t *lock = unit_schedule_lock_irqsave(v->sched_unit, &flags);
+ struct sched_unit *unit = v->sched_unit;
+ spinlock_t *lock = unit_schedule_lock_irqsave(unit, &flags);
- cpumask_and(&online_affinity, v->cpu_hard_affinity, c->cpu_valid);
+ cpumask_and(&online_affinity, unit->cpu_hard_affinity, c->cpu_valid);
if ( cpumask_empty(&online_affinity) &&
- cpumask_test_cpu(cpu, v->cpu_hard_affinity) )
+ cpumask_test_cpu(cpu, unit->cpu_hard_affinity) )
{
- if ( v->affinity_broken )
+ if ( unit->affinity_broken )
{
/* The vcpu is temporarily pinned, can't move it. */
- unit_schedule_unlock_irqrestore(lock, flags, v->sched_unit);
+ unit_schedule_unlock_irqrestore(lock, flags, unit);
ret = -EADDRINUSE;
break;
}
@@ -850,7 +867,7 @@ int cpu_disable_scheduler(unsigned int cpu)
if ( v->processor != cpu )
{
/* The vcpu is not on this cpu, so we can move on. */
- unit_schedule_unlock_irqrestore(lock, flags, v->sched_unit);
+ unit_schedule_unlock_irqrestore(lock, flags, unit);
continue;
}
@@ -863,7 +880,7 @@ int cpu_disable_scheduler(unsigned int cpu)
* things would have failed before getting in here.
*/
vcpu_migrate_start(v);
- unit_schedule_unlock_irqrestore(lock, flags, v->sched_unit);
+ unit_schedule_unlock_irqrestore(lock, flags, unit);
vcpu_migrate_finish(v);
@@ -892,7 +909,7 @@ static int cpu_disable_scheduler_check(unsigned int cpu)
for_each_domain_in_cpupool ( d, c )
for_each_vcpu ( d, v )
- if ( v->affinity_broken )
+ if ( v->sched_unit->affinity_broken )
return -EADDRINUSE;
return 0;
@@ -908,28 +925,31 @@ static int cpu_disable_scheduler_check(unsigned int cpu)
void sched_set_affinity(
struct vcpu *v, const cpumask_t *hard, const cpumask_t *soft)
{
- sched_adjust_affinity(dom_scheduler(v->domain), v->sched_unit, hard, soft);
+ struct sched_unit *unit = v->sched_unit;
+
+ sched_adjust_affinity(dom_scheduler(v->domain), unit, hard, soft);
if ( hard )
- cpumask_copy(v->cpu_hard_affinity, hard);
+ cpumask_copy(unit->cpu_hard_affinity, hard);
if ( soft )
- cpumask_copy(v->cpu_soft_affinity, soft);
+ cpumask_copy(unit->cpu_soft_affinity, soft);
- v->soft_aff_effective = !cpumask_subset(v->cpu_hard_affinity,
- v->cpu_soft_affinity) &&
- cpumask_intersects(v->cpu_soft_affinity,
- v->cpu_hard_affinity);
+ unit->soft_aff_effective = !cpumask_subset(unit->cpu_hard_affinity,
+ unit->cpu_soft_affinity) &&
+ cpumask_intersects(unit->cpu_soft_affinity,
+ unit->cpu_hard_affinity);
}
static int vcpu_set_affinity(
struct vcpu *v, const cpumask_t *affinity, const cpumask_t *which)
{
+ struct sched_unit *unit = v->sched_unit;
spinlock_t *lock;
int ret = 0;
- lock = unit_schedule_lock_irq(v->sched_unit);
+ lock = unit_schedule_lock_irq(unit);
- if ( v->affinity_broken )
+ if ( unit->affinity_broken )
ret = -EBUSY;
else
{
@@ -937,19 +957,19 @@ static int vcpu_set_affinity(
* Tell the scheduler we changes something about affinity,
* and ask to re-evaluate vcpu placement.
*/
- if ( which == v->cpu_hard_affinity )
+ if ( which == unit->cpu_hard_affinity )
{
sched_set_affinity(v, affinity, NULL);
}
else
{
- ASSERT(which == v->cpu_soft_affinity);
+ ASSERT(which == unit->cpu_soft_affinity);
sched_set_affinity(v, NULL, affinity);
}
vcpu_migrate_start(v);
}
- unit_schedule_unlock_irq(lock, v->sched_unit);
+ unit_schedule_unlock_irq(lock, unit);
domain_update_node_affinity(v->domain);
@@ -968,12 +988,12 @@ int vcpu_set_hard_affinity(struct vcpu *v, const cpumask_t *affinity)
if ( cpumask_empty(&online_affinity) )
return -EINVAL;
- return vcpu_set_affinity(v, affinity, v->cpu_hard_affinity);
+ return vcpu_set_affinity(v, affinity, v->sched_unit->cpu_hard_affinity);
}
int vcpu_set_soft_affinity(struct vcpu *v, const cpumask_t *affinity)
{
- return vcpu_set_affinity(v, affinity, v->cpu_soft_affinity);
+ return vcpu_set_affinity(v, affinity, v->sched_unit->cpu_soft_affinity);
}
/* Block the currently-executing domain until a pertinent event occurs. */
@@ -1167,28 +1187,30 @@ void watchdog_domain_destroy(struct domain *d)
int vcpu_pin_override(struct vcpu *v, int cpu)
{
+ struct sched_unit *unit = v->sched_unit;
spinlock_t *lock;
int ret = -EINVAL;
- lock = unit_schedule_lock_irq(v->sched_unit);
+ lock = unit_schedule_lock_irq(unit);
if ( cpu < 0 )
{
- if ( v->affinity_broken )
+ if ( unit->affinity_broken )
{
- sched_set_affinity(v, v->cpu_hard_affinity_saved, NULL);
- v->affinity_broken = 0;
+ sched_set_affinity(v, unit->cpu_hard_affinity_saved, NULL);
+ unit->affinity_broken = 0;
ret = 0;
}
}
else if ( cpu < nr_cpu_ids )
{
- if ( v->affinity_broken )
+ if ( unit->affinity_broken )
ret = -EBUSY;
else if ( cpumask_test_cpu(cpu, VCPU2ONLINE(v)) )
{
- cpumask_copy(v->cpu_hard_affinity_saved, v->cpu_hard_affinity);
- v->affinity_broken = 1;
+ cpumask_copy(unit->cpu_hard_affinity_saved,
+ unit->cpu_hard_affinity);
+ unit->affinity_broken = 1;
sched_set_affinity(v, cpumask_of(cpu), NULL);
ret = 0;
}
@@ -1197,7 +1219,7 @@ int vcpu_pin_override(struct vcpu *v, int cpu)
if ( ret == 0 )
vcpu_migrate_start(v);
- unit_schedule_unlock_irq(lock, v->sched_unit);
+ unit_schedule_unlock_irq(lock, unit);
domain_update_node_affinity(v->domain);
@@ -1549,7 +1571,7 @@ static void schedule(void)
((prev->pause_flags & VPF_blocked) ? RUNSTATE_blocked :
(vcpu_runnable(prev) ? RUNSTATE_runnable : RUNSTATE_offline)),
now);
- prev->last_run_time = now;
+ prev->sched_unit->last_run_time = now;
ASSERT(next->runstate.state != RUNSTATE_running);
vcpu_runstate_change(next, RUNSTATE_running, now);
@@ -132,7 +132,7 @@ static void __prepare_to_wait(struct waitqueue_vcpu *wqv)
/* Save current VCPU affinity; force wakeup on *this* CPU only. */
wqv->wakeup_cpu = smp_processor_id();
- cpumask_copy(&wqv->saved_affinity, curr->cpu_hard_affinity);
+ cpumask_copy(&wqv->saved_affinity, curr->sched_unit->cpu_hard_affinity);
if ( vcpu_set_hard_affinity(curr, cpumask_of(wqv->wakeup_cpu)) )
{
gdprintk(XENLOG_ERR, "Unable to set vcpu affinity\n");
@@ -199,7 +199,7 @@ void check_wakeup_from_wait(void)
{
/* Re-set VCPU affinity and re-enter the scheduler. */
struct vcpu *curr = current;
- cpumask_copy(&wqv->saved_affinity, curr->cpu_hard_affinity);
+ cpumask_copy(&wqv->saved_affinity, curr->sched_unit->cpu_hard_affinity);
if ( vcpu_set_hard_affinity(curr, cpumask_of(wqv->wakeup_cpu)) )
{
gdprintk(XENLOG_ERR, "Unable to set vcpu affinity\n");
@@ -438,11 +438,11 @@ static inline cpumask_t* cpupool_domain_cpumask(struct domain *d)
* * The hard affinity is not a subset of soft affinity
* * There is an overlap between the soft and hard affinity masks
*/
-static inline int has_soft_affinity(const struct vcpu *v)
+static inline int has_soft_affinity(const struct sched_unit *unit)
{
- return v->soft_aff_effective &&
- !cpumask_subset(cpupool_domain_cpumask(v->domain),
- v->cpu_soft_affinity);
+ return unit->soft_aff_effective &&
+ !cpumask_subset(cpupool_domain_cpumask(unit->vcpu->domain),
+ unit->cpu_soft_affinity);
}
/*
@@ -452,17 +452,18 @@ static inline int has_soft_affinity(const struct vcpu *v)
* to avoid running a vcpu where it would like, but is not allowed to!
*/
static inline void
-affinity_balance_cpumask(const struct vcpu *v, int step, cpumask_t *mask)
+affinity_balance_cpumask(const struct sched_unit *unit, int step,
+ cpumask_t *mask)
{
if ( step == BALANCE_SOFT_AFFINITY )
{
- cpumask_and(mask, v->cpu_soft_affinity, v->cpu_hard_affinity);
+ cpumask_and(mask, unit->cpu_soft_affinity, unit->cpu_hard_affinity);
if ( unlikely(cpumask_empty(mask)) )
- cpumask_copy(mask, v->cpu_hard_affinity);
+ cpumask_copy(mask, unit->cpu_hard_affinity);
}
else /* step == BALANCE_HARD_AFFINITY */
- cpumask_copy(mask, v->cpu_hard_affinity);
+ cpumask_copy(mask, unit->cpu_hard_affinity);
}
#endif /* __XEN_SCHED_IF_H__ */
@@ -175,9 +175,6 @@ struct vcpu
} runstate_guest; /* guest address */
#endif
- /* last time when vCPU is scheduled out */
- uint64_t last_run_time;
-
/* Has the FPU been initialised? */
bool fpu_initialised;
/* Has the FPU been used since it was last saved? */
@@ -203,8 +200,6 @@ struct vcpu
bool defer_shutdown;
/* VCPU is paused following shutdown request (d->is_shutting_down)? */
bool paused_for_shutdown;
- /* VCPU need affinity restored */
- bool affinity_broken;
/* A hypercall has been preempted. */
bool hcall_preempted;
@@ -213,9 +208,6 @@ struct vcpu
bool hcall_compat;
#endif
- /* Does soft affinity actually play a role (given hard affinity)? */
- bool soft_aff_effective;
-
/* The CPU, if any, which is holding onto this VCPU's state. */
#define VCPU_CPU_CLEAN (~0u)
unsigned int dirty_cpu;
@@ -247,16 +239,6 @@ struct vcpu
evtchn_port_t virq_to_evtchn[NR_VIRQS];
spinlock_t virq_lock;
- /* Bitmask of CPUs on which this VCPU may run. */
- cpumask_var_t cpu_hard_affinity;
- /* Used to change affinity temporarily. */
- cpumask_var_t cpu_hard_affinity_tmp;
- /* Used to restore affinity across S3. */
- cpumask_var_t cpu_hard_affinity_saved;
-
- /* Bitmask of CPUs on which this VCPU prefers to run. */
- cpumask_var_t cpu_soft_affinity;
-
/* Tasklet for continue_hypercall_on_cpu(). */
struct tasklet continue_hypercall_tasklet;
@@ -283,6 +265,22 @@ struct sched_unit {
void *priv; /* scheduler private data */
struct sched_unit *next_in_list;
struct sched_resource *res;
+
+ /* Last time when unit has been scheduled out. */
+ uint64_t last_run_time;
+
+ /* Item needs affinity restored. */
+ bool affinity_broken;
+ /* Does soft affinity actually play a role (given hard affinity)? */
+ bool soft_aff_effective;
+ /* Bitmask of CPUs on which this VCPU may run. */
+ cpumask_var_t cpu_hard_affinity;
+ /* Used to change affinity temporarily. */
+ cpumask_var_t cpu_hard_affinity_tmp;
+ /* Used to restore affinity across S3. */
+ cpumask_var_t cpu_hard_affinity_saved;
+ /* Bitmask of CPUs on which this VCPU prefers to run. */
+ cpumask_var_t cpu_soft_affinity;
};
#define for_each_sched_unit(d, e) \
@@ -980,7 +978,7 @@ static inline bool is_hvm_vcpu(const struct vcpu *v)
static inline bool is_hwdom_pinned_vcpu(const struct vcpu *v)
{
return (is_hardware_domain(v->domain) &&
- cpumask_weight(v->cpu_hard_affinity) == 1);
+ cpumask_weight(v->sched_unit->cpu_hard_affinity) == 1);
}
#ifdef CONFIG_HAS_PASSTHROUGH
Affinities are scheduler specific attributes, they should be per scheduling unit. So move all affinity related fields in struct vcpu to struct sched_unit. While at it switch affinity related functions in sched-if.h to use a pointer to sched_unit instead to vcpu as parameter. vcpu->last_run_time is primarily used by sched_credit, so move it to struct sched_unit, too. Signed-off-by: Juergen Gross <jgross@suse.com> --- xen/arch/x86/pv/emul-priv-op.c | 1 + xen/arch/x86/pv/traps.c | 5 +- xen/arch/x86/traps.c | 9 ++-- xen/common/domain.c | 19 ++----- xen/common/domctl.c | 13 +++-- xen/common/keyhandler.c | 4 +- xen/common/sched_credit.c | 20 ++++---- xen/common/sched_credit2.c | 42 ++++++++-------- xen/common/sched_null.c | 16 +++--- xen/common/sched_rt.c | 9 ++-- xen/common/schedule.c | 110 ++++++++++++++++++++++++----------------- xen/common/wait.c | 4 +- xen/include/xen/sched-if.h | 17 ++++--- xen/include/xen/sched.h | 36 +++++++------- 14 files changed, 163 insertions(+), 142 deletions(-)