/* Propagate event elapsed time into the generic event. Can only be executed on the CPU where the event is active. Returns the delta events processed.  */
static u64 x86_perf_event_update(struct perf_event *event, struct hw_perf_event *hwc, int idx)
/* Propagate event elapsed time into the generic event. Can only be executed on the CPU where the event is active. Returns the delta events processed.  */
static u64 x86_perf_event_update(struct perf_event *event, struct hw_perf_event *hwc, int idx)
{
	int shift = 64 - x86_pmu.event_bits;
	u64 prev_raw_count, new_raw_count;
	s64 delta;
	if (idx == X86_PMC_IDX_FIXED_BTS)
		return 0;
again:
	prev_raw_count = atomic64_read(&hwc->prev_count);
	rdmsrl(hwc->event_base + idx, new_raw_count);
	if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count,
					new_raw_count) != prev_raw_count)
		goto again;
	delta = (new_raw_count << shift) - (prev_raw_count << shift);
	delta >>= shift;
	atomic64_add(delta, &event->count);
	atomic64_sub(delta, &hwc->period_left);
	return new_raw_count;
}