u64 state_time;
struct vcpu_runstate_info *state;
- preempt_disable();
+ BUG_ON(preemptible());
state = &__get_cpu_var(runstate);
*res = *state;
barrier();
} while (get64(&state->state_entry_time) != state_time);
-
- preempt_enable();
}
static void setup_runstate_info(int cpu)
unsigned long long xen_sched_clock(void)
{
struct vcpu_runstate_info state;
- cycle_t now = xen_clocksource_read();
+ cycle_t now;
+ u64 ret;
s64 offset;
+ /*
+ * Ideally sched_clock should be called on a per-cpu basis
+ * anyway, so preempt should already be disabled, but that's
+ * not current practice at the moment.
+ */
+ preempt_disable();
+
+ now = xen_clocksource_read();
+
get_runstate_snapshot(&state);
WARN_ON(state.state != RUNSTATE_running);
if (offset < 0)
offset = 0;
- return state.time[RUNSTATE_blocked] +
+ ret = state.time[RUNSTATE_blocked] +
state.time[RUNSTATE_running] +
offset;
+
+ preempt_enable();
+
+ return ret;
}
break;
case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_RESUME:
break;
case CLOCK_EVT_MODE_UNUSED:
HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL))
BUG();
break;
+ case CLOCK_EVT_MODE_RESUME:
+ break;
}
}
return ret;
}
-static void xen_setup_timer(int cpu)
+void xen_setup_timer(int cpu)
{
const char *name;
struct clock_event_device *evt;
IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
name, NULL);
- evt = &get_cpu_var(xen_clock_events);
+ evt = &per_cpu(xen_clock_events, cpu);
memcpy(evt, xen_clockevent, sizeof(*evt));
evt->cpumask = cpumask_of_cpu(cpu);
evt->irq = irq;
- clockevents_register_device(evt);
setup_runstate_info(cpu);
+}
+
+void xen_setup_cpu_clockevents(void)
+{
+ BUG_ON(preemptible());
- put_cpu_var(xen_clock_events);
+ clockevents_register_device(&__get_cpu_var(xen_clock_events));
}
__init void xen_time_init(void)
tsc_disable = 0;
xen_setup_timer(cpu);
+ xen_setup_cpu_clockevents();
}