[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC PATCH v1 2/6] sched: track time spent in hypervisor tasks
In most cases hypervisor code performs guest-related jobs. Tasks like hypercall handling or MMIO access emulation are done for calling vCPU so it is okay to charge time spent in hypervisor to the current vCPU. But, there are also tasks that are not originated from guests. This includes things like TLB flushing or running tasklets. We don't want to track time spent in this tasks to a total scheduling unit run time. So we need to track time spent in such housekeeping tasks separately. Those hypervisor tasks are run in do_softirq() function, so we'll install our hooks there. TODO: This change is not tested on ARM, and probably we'll get a failing assertion there. This is because ARM code exits from schedule() and have chance to get to end of do_softirq(). Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk@xxxxxxxx> --- xen/common/sched/core.c | 32 ++++++++++++++++++++++++++++++++ xen/common/softirq.c | 2 ++ xen/include/xen/sched.h | 16 +++++++++++++++- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/xen/common/sched/core.c b/xen/common/sched/core.c index 8f642ada05..d597811fef 100644 --- a/xen/common/sched/core.c +++ b/xen/common/sched/core.c @@ -945,6 +945,37 @@ void vcpu_end_irq_handler(void) atomic_add(delta, ¤t->sched_unit->irq_time); } +void vcpu_begin_hyp_task(struct vcpu *v) +{ + if ( is_idle_vcpu(v) ) + return; + + ASSERT(!v->in_hyp_task); + + v->hyp_entry_time = NOW(); +#ifndef NDEBUG + v->in_hyp_task = true; +#endif +} + +void vcpu_end_hyp_task(struct vcpu *v) +{ + int delta; + + if ( is_idle_vcpu(v) ) + return; + + ASSERT(v->in_hyp_task); + + /* We assume that hypervisor task time will not overflow int */ + delta = NOW() - v->hyp_entry_time; + atomic_add(delta, &v->sched_unit->hyp_time); + +#ifndef NDEBUG + v->in_hyp_task = false; +#endif +} + /* * Do the actual movement of an unit from old to new CPU. Locks for *both* * CPUs needs to have been taken already when calling this! @@ -2615,6 +2646,7 @@ static void schedule(void) SCHED_STAT_CRANK(sched_run); + vcpu_end_hyp_task(current); rcu_read_lock(&sched_res_rculock); lock = pcpu_schedule_lock_irq(cpu); diff --git a/xen/common/softirq.c b/xen/common/softirq.c index 063e93cbe3..03a29384d1 100644 --- a/xen/common/softirq.c +++ b/xen/common/softirq.c @@ -71,7 +71,9 @@ void process_pending_softirqs(void) void do_softirq(void) { ASSERT_NOT_IN_ATOMIC(); + vcpu_begin_hyp_task(current); __do_softirq(0); + vcpu_end_hyp_task(current); } void open_softirq(int nr, softirq_handler handler) diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index ceed53364b..51dc7c4551 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -239,7 +239,12 @@ struct vcpu /* Fair scheduling state */ uint64_t irq_entry_time; + uint64_t hyp_entry_time; unsigned int irq_nesting; +#ifndef NDEBUG + bool in_hyp_task; +#endif + /* Tasklet for continue_hypercall_on_cpu(). */ struct tasklet continue_hypercall_tasklet; @@ -279,8 +284,9 @@ struct sched_unit { /* Vcpu state summary. */ unsigned int runstate_cnt[4]; - /* Fair scheduling correction value */ + /* Fair scheduling correction values */ atomic_t irq_time; + atomic_t hyp_time; /* Bitmask of CPUs on which this VCPU may run. */ cpumask_var_t cpu_hard_affinity; @@ -703,6 +709,14 @@ void vcpu_sleep_sync(struct vcpu *v); void vcpu_begin_irq_handler(void); void vcpu_end_irq_handler(void); +/* + * Report to scheduler when we are doing housekeeping tasks on the + * current vcpu. This is called during do_softirq() but can be called + * anywhere else. + */ +void vcpu_begin_hyp_task(struct vcpu *v); +void vcpu_end_hyp_task(struct vcpu *v); + /* * Force synchronisation of given VCPU's state. If it is currently descheduled, * this call will ensure that all its state is committed to memory and that -- 2.27.0
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |