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

ppc_cbe_cpufreq_pmi.c (3177B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * pmi backend for the cbe_cpufreq driver
      4 *
      5 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
      6 *
      7 * Author: Christian Krafft <krafft@de.ibm.com>
      8 */
      9
     10#include <linux/kernel.h>
     11#include <linux/types.h>
     12#include <linux/timer.h>
     13#include <linux/init.h>
     14#include <linux/of_platform.h>
     15#include <linux/pm_qos.h>
     16#include <linux/slab.h>
     17
     18#include <asm/processor.h>
     19#include <asm/pmi.h>
     20#include <asm/cell-regs.h>
     21
     22#ifdef DEBUG
     23#include <asm/time.h>
     24#endif
     25
     26#include "ppc_cbe_cpufreq.h"
     27
     28bool cbe_cpufreq_has_pmi = false;
     29EXPORT_SYMBOL_GPL(cbe_cpufreq_has_pmi);
     30
     31/*
     32 * hardware specific functions
     33 */
     34
     35int cbe_cpufreq_set_pmode_pmi(int cpu, unsigned int pmode)
     36{
     37	int ret;
     38	pmi_message_t pmi_msg;
     39#ifdef DEBUG
     40	long time;
     41#endif
     42	pmi_msg.type = PMI_TYPE_FREQ_CHANGE;
     43	pmi_msg.data1 =	cbe_cpu_to_node(cpu);
     44	pmi_msg.data2 = pmode;
     45
     46#ifdef DEBUG
     47	time = jiffies;
     48#endif
     49	pmi_send_message(pmi_msg);
     50
     51#ifdef DEBUG
     52	time = jiffies  - time;
     53	time = jiffies_to_msecs(time);
     54	pr_debug("had to wait %lu ms for a transition using " \
     55		 "PMI\n", time);
     56#endif
     57	ret = pmi_msg.data2;
     58	pr_debug("PMI returned slow mode %d\n", ret);
     59
     60	return ret;
     61}
     62EXPORT_SYMBOL_GPL(cbe_cpufreq_set_pmode_pmi);
     63
     64
     65static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg)
     66{
     67	struct cpufreq_policy *policy;
     68	struct freq_qos_request *req;
     69	u8 node, slow_mode;
     70	int cpu, ret;
     71
     72	BUG_ON(pmi_msg.type != PMI_TYPE_FREQ_CHANGE);
     73
     74	node = pmi_msg.data1;
     75	slow_mode = pmi_msg.data2;
     76
     77	cpu = cbe_node_to_cpu(node);
     78
     79	pr_debug("cbe_handle_pmi: node: %d max_freq: %d\n", node, slow_mode);
     80
     81	policy = cpufreq_cpu_get(cpu);
     82	if (!policy) {
     83		pr_warn("cpufreq policy not found cpu%d\n", cpu);
     84		return;
     85	}
     86
     87	req = policy->driver_data;
     88
     89	ret = freq_qos_update_request(req,
     90			policy->freq_table[slow_mode].frequency);
     91	if (ret < 0)
     92		pr_warn("Failed to update freq constraint: %d\n", ret);
     93	else
     94		pr_debug("limiting node %d to slow mode %d\n", node, slow_mode);
     95
     96	cpufreq_cpu_put(policy);
     97}
     98
     99static struct pmi_handler cbe_pmi_handler = {
    100	.type			= PMI_TYPE_FREQ_CHANGE,
    101	.handle_pmi_message	= cbe_cpufreq_handle_pmi,
    102};
    103
    104void cbe_cpufreq_pmi_policy_init(struct cpufreq_policy *policy)
    105{
    106	struct freq_qos_request *req;
    107	int ret;
    108
    109	if (!cbe_cpufreq_has_pmi)
    110		return;
    111
    112	req = kzalloc(sizeof(*req), GFP_KERNEL);
    113	if (!req)
    114		return;
    115
    116	ret = freq_qos_add_request(&policy->constraints, req, FREQ_QOS_MAX,
    117				   policy->freq_table[0].frequency);
    118	if (ret < 0) {
    119		pr_err("Failed to add freq constraint (%d)\n", ret);
    120		kfree(req);
    121		return;
    122	}
    123
    124	policy->driver_data = req;
    125}
    126EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_policy_init);
    127
    128void cbe_cpufreq_pmi_policy_exit(struct cpufreq_policy *policy)
    129{
    130	struct freq_qos_request *req = policy->driver_data;
    131
    132	if (cbe_cpufreq_has_pmi) {
    133		freq_qos_remove_request(req);
    134		kfree(req);
    135	}
    136}
    137EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_policy_exit);
    138
    139void cbe_cpufreq_pmi_init(void)
    140{
    141	if (!pmi_register_handler(&cbe_pmi_handler))
    142		cbe_cpufreq_has_pmi = true;
    143}
    144EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_init);
    145
    146void cbe_cpufreq_pmi_exit(void)
    147{
    148	pmi_unregister_handler(&cbe_pmi_handler);
    149	cbe_cpufreq_has_pmi = false;
    150}
    151EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_exit);