>From f27da1aba6c9c92add4f88b4dcec517e5e321caa Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Fri, 20 May 2016 12:25:58 +0200 Subject: [PATCH 3/3] xen: support runqueue steal time on xen Up to now reading the stolen time of a remote cpu was not possible in a performant way under Xen. This made support of runqueue steal time via paravirt_steal_rq_enabled impossible. With the addition of an appropriate hypervisor interface this is now possible, so add the support. Signed-off-by: Juergen Gross --- drivers/xen/time.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/drivers/xen/time.c b/drivers/xen/time.c index 2257b66..04b6cb7 100644 --- a/drivers/xen/time.c +++ b/drivers/xen/time.c @@ -19,6 +19,9 @@ /* runstate info updated by Xen */ static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate); +/* runstate info of remote cpu accessible */ +static bool xen_runstate_remote; + /* return an consistent snapshot of 64-bit time/counter value */ static u64 get64(const u64 *p) { @@ -47,27 +50,31 @@ static u64 get64(const u64 *p) return ret; } -/* - * Runstate accounting - */ -void xen_get_runstate_snapshot(struct vcpu_runstate_info *res) +static void xen_get_runstate_snapshot_cpu(struct vcpu_runstate_info *res, + unsigned cpu) { u64 state_time; struct vcpu_runstate_info *state; BUG_ON(preemptible()); - state = this_cpu_ptr(&xen_runstate); + state = per_cpu_ptr(&xen_runstate, cpu); - /* - * The runstate info is always updated by the hypervisor on - * the current CPU, so there's no need to use anything - * stronger than a compiler barrier when fetching it. - */ do { state_time = get64(&state->state_entry_time); + rmb(); *res = READ_ONCE(*state); - } while (get64(&state->state_entry_time) != state_time); + rmb(); + } while (get64(&state->state_entry_time) != state_time || + (state_time & XEN_RUNSTATE_UPDATE)); +} + +/* + * Runstate accounting + */ +void xen_get_runstate_snapshot(struct vcpu_runstate_info *res) +{ + xen_get_runstate_snapshot_cpu(res, smp_processor_id()); } /* return true when a vcpu could run but has no real cpu to run on */ @@ -80,8 +87,8 @@ static u64 xen_steal_clock(int cpu) { struct vcpu_runstate_info state; - BUG_ON(cpu != smp_processor_id()); - xen_get_runstate_snapshot(&state); + BUG_ON(!xen_runstate_remote && cpu != smp_processor_id()); + xen_get_runstate_snapshot_cpu(&state, cpu); return state.time[RUNSTATE_runnable] + state.time[RUNSTATE_offline]; } @@ -98,11 +105,12 @@ void xen_setup_runstate_info(int cpu) void __init xen_time_setup_guest(void) { + xen_runstate_remote = !HYPERVISOR_vm_assist(VMASST_CMD_enable, + VMASST_TYPE_runstate_update_flag); + pv_time_ops.steal_clock = xen_steal_clock; static_key_slow_inc(¶virt_steal_enabled); - /* - * We can't set paravirt_steal_rq_enabled as this would require the - * capability to read another cpu's runstate info. - */ + if (xen_runstate_remote) + static_key_slow_inc(¶virt_steal_rq_enabled); } -- 2.6.6