cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

windfarm_cpufreq_clamp.c (2679B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2#include <linux/types.h>
      3#include <linux/errno.h>
      4#include <linux/kernel.h>
      5#include <linux/delay.h>
      6#include <linux/pm_qos.h>
      7#include <linux/slab.h>
      8#include <linux/init.h>
      9#include <linux/wait.h>
     10#include <linux/cpu.h>
     11#include <linux/cpufreq.h>
     12
     13#include "windfarm.h"
     14
     15#define VERSION "0.3"
     16
     17static int clamped;
     18static struct wf_control *clamp_control;
     19static struct freq_qos_request qos_req;
     20static unsigned int min_freq, max_freq;
     21
     22static int clamp_set(struct wf_control *ct, s32 value)
     23{
     24	unsigned int freq;
     25
     26	if (value) {
     27		freq = min_freq;
     28		printk(KERN_INFO "windfarm: Clamping CPU frequency to "
     29		       "minimum !\n");
     30	} else {
     31		freq = max_freq;
     32		printk(KERN_INFO "windfarm: CPU frequency unclamped !\n");
     33	}
     34	clamped = value;
     35
     36	return freq_qos_update_request(&qos_req, freq);
     37}
     38
     39static int clamp_get(struct wf_control *ct, s32 *value)
     40{
     41	*value = clamped;
     42	return 0;
     43}
     44
     45static s32 clamp_min(struct wf_control *ct)
     46{
     47	return 0;
     48}
     49
     50static s32 clamp_max(struct wf_control *ct)
     51{
     52	return 1;
     53}
     54
     55static const struct wf_control_ops clamp_ops = {
     56	.set_value	= clamp_set,
     57	.get_value	= clamp_get,
     58	.get_min	= clamp_min,
     59	.get_max	= clamp_max,
     60	.owner		= THIS_MODULE,
     61};
     62
     63static int __init wf_cpufreq_clamp_init(void)
     64{
     65	struct cpufreq_policy *policy;
     66	struct wf_control *clamp;
     67	struct device *dev;
     68	int ret;
     69
     70	policy = cpufreq_cpu_get(0);
     71	if (!policy) {
     72		pr_warn("%s: cpufreq policy not found cpu0\n", __func__);
     73		return -EPROBE_DEFER;
     74	}
     75
     76	min_freq = policy->cpuinfo.min_freq;
     77	max_freq = policy->cpuinfo.max_freq;
     78
     79	ret = freq_qos_add_request(&policy->constraints, &qos_req, FREQ_QOS_MAX,
     80				   max_freq);
     81
     82	cpufreq_cpu_put(policy);
     83
     84	if (ret < 0) {
     85		pr_err("%s: Failed to add freq constraint (%d)\n", __func__,
     86		       ret);
     87		return ret;
     88	}
     89
     90	dev = get_cpu_device(0);
     91	if (unlikely(!dev)) {
     92		pr_warn("%s: No cpu device for cpu0\n", __func__);
     93		ret = -ENODEV;
     94		goto fail;
     95	}
     96
     97	clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL);
     98	if (clamp == NULL) {
     99		ret = -ENOMEM;
    100		goto fail;
    101	}
    102
    103	clamp->ops = &clamp_ops;
    104	clamp->name = "cpufreq-clamp";
    105	ret = wf_register_control(clamp);
    106	if (ret)
    107		goto free;
    108
    109	clamp_control = clamp;
    110	return 0;
    111
    112 free:
    113	kfree(clamp);
    114 fail:
    115	freq_qos_remove_request(&qos_req);
    116	return ret;
    117}
    118
    119static void __exit wf_cpufreq_clamp_exit(void)
    120{
    121	if (clamp_control) {
    122		wf_unregister_control(clamp_control);
    123		freq_qos_remove_request(&qos_req);
    124	}
    125}
    126
    127
    128module_init(wf_cpufreq_clamp_init);
    129module_exit(wf_cpufreq_clamp_exit);
    130
    131MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
    132MODULE_DESCRIPTION("CPU frequency clamp for PowerMacs thermal control");
    133MODULE_LICENSE("GPL");
    134