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

processor_thermal_rapl.c (3434B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * processor thermal device RFIM control
      4 * Copyright (c) 2020, Intel Corporation.
      5 */
      6
      7#include <linux/kernel.h>
      8#include <linux/module.h>
      9#include <linux/pci.h>
     10#include "processor_thermal_device.h"
     11
     12static struct rapl_if_priv rapl_mmio_priv;
     13
     14static const struct rapl_mmio_regs rapl_mmio_default = {
     15	.reg_unit = 0x5938,
     16	.regs[RAPL_DOMAIN_PACKAGE] = { 0x59a0, 0x593c, 0x58f0, 0, 0x5930},
     17	.regs[RAPL_DOMAIN_DRAM] = { 0x58e0, 0x58e8, 0x58ec, 0, 0},
     18	.limits[RAPL_DOMAIN_PACKAGE] = 2,
     19	.limits[RAPL_DOMAIN_DRAM] = 2,
     20};
     21
     22static int rapl_mmio_cpu_online(unsigned int cpu)
     23{
     24	struct rapl_package *rp;
     25
     26	/* mmio rapl supports package 0 only for now */
     27	if (topology_physical_package_id(cpu))
     28		return 0;
     29
     30	rp = rapl_find_package_domain(cpu, &rapl_mmio_priv);
     31	if (!rp) {
     32		rp = rapl_add_package(cpu, &rapl_mmio_priv);
     33		if (IS_ERR(rp))
     34			return PTR_ERR(rp);
     35	}
     36	cpumask_set_cpu(cpu, &rp->cpumask);
     37	return 0;
     38}
     39
     40static int rapl_mmio_cpu_down_prep(unsigned int cpu)
     41{
     42	struct rapl_package *rp;
     43	int lead_cpu;
     44
     45	rp = rapl_find_package_domain(cpu, &rapl_mmio_priv);
     46	if (!rp)
     47		return 0;
     48
     49	cpumask_clear_cpu(cpu, &rp->cpumask);
     50	lead_cpu = cpumask_first(&rp->cpumask);
     51	if (lead_cpu >= nr_cpu_ids)
     52		rapl_remove_package(rp);
     53	else if (rp->lead_cpu == cpu)
     54		rp->lead_cpu = lead_cpu;
     55	return 0;
     56}
     57
     58static int rapl_mmio_read_raw(int cpu, struct reg_action *ra)
     59{
     60	if (!ra->reg)
     61		return -EINVAL;
     62
     63	ra->value = readq((void __iomem *)ra->reg);
     64	ra->value &= ra->mask;
     65	return 0;
     66}
     67
     68static int rapl_mmio_write_raw(int cpu, struct reg_action *ra)
     69{
     70	u64 val;
     71
     72	if (!ra->reg)
     73		return -EINVAL;
     74
     75	val = readq((void __iomem *)ra->reg);
     76	val &= ~ra->mask;
     77	val |= ra->value;
     78	writeq(val, (void __iomem *)ra->reg);
     79	return 0;
     80}
     81
     82int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
     83{
     84	const struct rapl_mmio_regs *rapl_regs = &rapl_mmio_default;
     85	enum rapl_domain_reg_id reg;
     86	enum rapl_domain_type domain;
     87	int ret;
     88
     89	if (!rapl_regs)
     90		return 0;
     91
     92	for (domain = RAPL_DOMAIN_PACKAGE; domain < RAPL_DOMAIN_MAX; domain++) {
     93		for (reg = RAPL_DOMAIN_REG_LIMIT; reg < RAPL_DOMAIN_REG_MAX; reg++)
     94			if (rapl_regs->regs[domain][reg])
     95				rapl_mmio_priv.regs[domain][reg] =
     96						(u64)proc_priv->mmio_base +
     97						rapl_regs->regs[domain][reg];
     98		rapl_mmio_priv.limits[domain] = rapl_regs->limits[domain];
     99	}
    100	rapl_mmio_priv.reg_unit = (u64)proc_priv->mmio_base + rapl_regs->reg_unit;
    101
    102	rapl_mmio_priv.read_raw = rapl_mmio_read_raw;
    103	rapl_mmio_priv.write_raw = rapl_mmio_write_raw;
    104
    105	rapl_mmio_priv.control_type = powercap_register_control_type(NULL, "intel-rapl-mmio", NULL);
    106	if (IS_ERR(rapl_mmio_priv.control_type)) {
    107		pr_debug("failed to register powercap control_type.\n");
    108		return PTR_ERR(rapl_mmio_priv.control_type);
    109	}
    110
    111	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powercap/rapl:online",
    112				rapl_mmio_cpu_online, rapl_mmio_cpu_down_prep);
    113	if (ret < 0) {
    114		powercap_unregister_control_type(rapl_mmio_priv.control_type);
    115		rapl_mmio_priv.control_type = NULL;
    116		return ret;
    117	}
    118	rapl_mmio_priv.pcap_rapl_online = ret;
    119
    120	return 0;
    121}
    122EXPORT_SYMBOL_GPL(proc_thermal_rapl_add);
    123
    124void proc_thermal_rapl_remove(void)
    125{
    126	if (IS_ERR_OR_NULL(rapl_mmio_priv.control_type))
    127		return;
    128
    129	cpuhp_remove_state(rapl_mmio_priv.pcap_rapl_online);
    130	powercap_unregister_control_type(rapl_mmio_priv.control_type);
    131}
    132EXPORT_SYMBOL_GPL(proc_thermal_rapl_remove);
    133
    134MODULE_LICENSE("GPL v2");