[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [RFC PATCH v1 2/6] sched: track time spent in hypervisor tasks
On 12.06.20 02:22, Volodymyr Babchuk wrote: 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 */ This will definitely happen for long running VMs. Please use a 64-bit variable. + 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); This won't work for scheduling. current will either have changed, or in x86 case __do_softirq() might just not return. You need to handle that case explicitly in schedule() (you did that for the old vcpu, but for the case schedule() is returning you need to call vcpu_begin_hyp_task(current) there). Juergen
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |