cregit-Linux how code gets into the kernel

Release 4.15 arch/x86/kernel/cpu/aperfmperf.c

/*
 * x86 APERF/MPERF KHz calculation for
 * /sys/.../cpufreq/scaling_cur_freq
 *
 * Copyright (C) 2017 Intel Corp.
 * Author: Len Brown <len.brown@intel.com>
 *
 * This file is licensed under GPLv2.
 */

#include <linux/delay.h>
#include <linux/ktime.h>
#include <linux/math64.h>
#include <linux/percpu.h>
#include <linux/smp.h>

#include "cpu.h"


struct aperfmperf_sample {
	
unsigned int	khz;
	
ktime_t	time;
	
u64	aperf;
	
u64	mperf;
};

static DEFINE_PER_CPU(struct aperfmperf_sample, samples);


#define APERFMPERF_CACHE_THRESHOLD_MS	10

#define APERFMPERF_REFRESH_DELAY_MS	10

#define APERFMPERF_STALE_THRESHOLD_MS	1000

/*
 * aperfmperf_snapshot_khz()
 * On the current CPU, snapshot APERF, MPERF, and jiffies
 * unless we already did it within 10ms
 * calculate kHz, save snapshot
 */

static void aperfmperf_snapshot_khz(void *dummy) { u64 aperf, aperf_delta; u64 mperf, mperf_delta; struct aperfmperf_sample *s = this_cpu_ptr(&samples); unsigned long flags; local_irq_save(flags); rdmsrl(MSR_IA32_APERF, aperf); rdmsrl(MSR_IA32_MPERF, mperf); local_irq_restore(flags); aperf_delta = aperf - s->aperf; mperf_delta = mperf - s->mperf; /* * There is no architectural guarantee that MPERF * increments faster than we can read it. */ if (mperf_delta == 0) return; s->time = ktime_get(); s->aperf = aperf; s->mperf = mperf; s->khz = div64_u64((cpu_khz * aperf_delta), mperf_delta); }

Contributors

PersonTokensPropCommitsCommitProp
Len Brown8068.38%125.00%
Rafael J. Wysocki2319.66%250.00%
Doug Smythies1411.97%125.00%
Total117100.00%4100.00%


static bool aperfmperf_snapshot_cpu(int cpu, ktime_t now, bool wait) { s64 time_delta = ktime_ms_delta(now, per_cpu(samples.time, cpu)); /* Don't bother re-computing within the cache threshold time. */ if (time_delta < APERFMPERF_CACHE_THRESHOLD_MS) return true; smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, wait); /* Return false if the previous iteration was too long ago. */ return time_delta <= APERFMPERF_STALE_THRESHOLD_MS; }

Contributors

PersonTokensPropCommitsCommitProp
Rafael J. Wysocki5491.53%266.67%
Len Brown58.47%133.33%
Total59100.00%3100.00%


unsigned int aperfmperf_get_khz(int cpu) { if (!cpu_khz) return 0; if (!static_cpu_has(X86_FEATURE_APERFMPERF)) return 0; aperfmperf_snapshot_cpu(cpu, ktime_get(), true); return per_cpu(samples.khz, cpu); }

Contributors

PersonTokensPropCommitsCommitProp
Rafael J. Wysocki2960.42%375.00%
Len Brown1939.58%125.00%
Total48100.00%4100.00%


void arch_freq_prepare_all(void) { ktime_t now = ktime_get(); bool wait = false; int cpu; if (!cpu_khz) return; if (!static_cpu_has(X86_FEATURE_APERFMPERF)) return; for_each_online_cpu(cpu) if (!aperfmperf_snapshot_cpu(cpu, now, false)) wait = true; if (wait) msleep(APERFMPERF_REFRESH_DELAY_MS); }

Contributors

PersonTokensPropCommitsCommitProp
Rafael J. Wysocki65100.00%2100.00%
Total65100.00%2100.00%


unsigned int arch_freq_get_on_cpu(int cpu) { if (!cpu_khz) return 0; if (!static_cpu_has(X86_FEATURE_APERFMPERF)) return 0; if (aperfmperf_snapshot_cpu(cpu, ktime_get(), true)) return per_cpu(samples.khz, cpu); msleep(APERFMPERF_REFRESH_DELAY_MS); smp_call_function_single(cpu, aperfmperf_snapshot_khz, NULL, 1); return per_cpu(samples.khz, cpu); }

Contributors

PersonTokensPropCommitsCommitProp
Rafael J. Wysocki6078.95%375.00%
Len Brown1621.05%125.00%
Total76100.00%4100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Rafael J. Wysocki25259.43%360.00%
Len Brown15837.26%120.00%
Doug Smythies143.30%120.00%
Total424100.00%5100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.