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_rfim.c (8312B)


      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
     12MODULE_IMPORT_NS(INT340X_THERMAL);
     13
     14struct mmio_reg {
     15	int read_only;
     16	u32 offset;
     17	int bits;
     18	u16 mask;
     19	u16 shift;
     20};
     21
     22/* These will represent sysfs attribute names */
     23static const char * const fivr_strings[] = {
     24	"vco_ref_code_lo",
     25	"vco_ref_code_hi",
     26	"spread_spectrum_pct",
     27	"spread_spectrum_clk_enable",
     28	"rfi_vco_ref_code",
     29	"fivr_fffc_rev",
     30	NULL
     31};
     32
     33static const struct mmio_reg tgl_fivr_mmio_regs[] = {
     34	{ 0, 0x5A18, 3, 0x7, 11}, /* vco_ref_code_lo */
     35	{ 0, 0x5A18, 8, 0xFF, 16}, /* vco_ref_code_hi */
     36	{ 0, 0x5A08, 8, 0xFF, 0}, /* spread_spectrum_pct */
     37	{ 0, 0x5A08, 1, 0x1, 8}, /* spread_spectrum_clk_enable */
     38	{ 1, 0x5A10, 12, 0xFFF, 0}, /* rfi_vco_ref_code */
     39	{ 1, 0x5A14, 2, 0x3, 1}, /* fivr_fffc_rev */
     40};
     41
     42/* These will represent sysfs attribute names */
     43static const char * const dvfs_strings[] = {
     44	"rfi_restriction_run_busy",
     45	"rfi_restriction_err_code",
     46	"rfi_restriction_data_rate",
     47	"rfi_restriction_data_rate_base",
     48	"ddr_data_rate_point_0",
     49	"ddr_data_rate_point_1",
     50	"ddr_data_rate_point_2",
     51	"ddr_data_rate_point_3",
     52	"rfi_disable",
     53	NULL
     54};
     55
     56static const struct mmio_reg adl_dvfs_mmio_regs[] = {
     57	{ 0, 0x5A38, 1, 0x1, 31}, /* rfi_restriction_run_busy */
     58	{ 0, 0x5A38, 7, 0x7F, 24}, /* rfi_restriction_err_code */
     59	{ 0, 0x5A38, 8, 0xFF, 16}, /* rfi_restriction_data_rate */
     60	{ 0, 0x5A38, 16, 0xFFFF, 0}, /* rfi_restriction_data_rate_base */
     61	{ 0, 0x5A30, 10, 0x3FF, 0}, /* ddr_data_rate_point_0 */
     62	{ 0, 0x5A30, 10, 0x3FF, 10}, /* ddr_data_rate_point_1 */
     63	{ 0, 0x5A30, 10, 0x3FF, 20}, /* ddr_data_rate_point_2 */
     64	{ 0, 0x5A30, 10, 0x3FF, 30}, /* ddr_data_rate_point_3 */
     65	{ 0, 0x5A40, 1, 0x1, 0}, /* rfi_disable */
     66};
     67
     68#define RFIM_SHOW(suffix, table)\
     69static ssize_t suffix##_show(struct device *dev,\
     70			      struct device_attribute *attr,\
     71			      char *buf)\
     72{\
     73	struct proc_thermal_device *proc_priv;\
     74	struct pci_dev *pdev = to_pci_dev(dev);\
     75	const struct mmio_reg *mmio_regs;\
     76	const char **match_strs;\
     77	u32 reg_val;\
     78	int ret;\
     79\
     80	proc_priv = pci_get_drvdata(pdev);\
     81	if (table) {\
     82		match_strs = (const char **)dvfs_strings;\
     83		mmio_regs = adl_dvfs_mmio_regs;\
     84	} else { \
     85		match_strs = (const char **)fivr_strings;\
     86		mmio_regs = tgl_fivr_mmio_regs;\
     87	} \
     88	\
     89	ret = match_string(match_strs, -1, attr->attr.name);\
     90	if (ret < 0)\
     91		return ret;\
     92	reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
     93	ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask;\
     94	return sprintf(buf, "%u\n", ret);\
     95}
     96
     97#define RFIM_STORE(suffix, table)\
     98static ssize_t suffix##_store(struct device *dev,\
     99			       struct device_attribute *attr,\
    100			       const char *buf, size_t count)\
    101{\
    102	struct proc_thermal_device *proc_priv;\
    103	struct pci_dev *pdev = to_pci_dev(dev);\
    104	unsigned int input;\
    105	const char **match_strs;\
    106	const struct mmio_reg *mmio_regs;\
    107	int ret, err;\
    108	u32 reg_val;\
    109	u32 mask;\
    110\
    111	proc_priv = pci_get_drvdata(pdev);\
    112	if (table) {\
    113		match_strs = (const char **)dvfs_strings;\
    114		mmio_regs = adl_dvfs_mmio_regs;\
    115	} else { \
    116		match_strs = (const char **)fivr_strings;\
    117		mmio_regs = tgl_fivr_mmio_regs;\
    118	} \
    119	\
    120	ret = match_string(match_strs, -1, attr->attr.name);\
    121	if (ret < 0)\
    122		return ret;\
    123	if (mmio_regs[ret].read_only)\
    124		return -EPERM;\
    125	err = kstrtouint(buf, 10, &input);\
    126	if (err)\
    127		return err;\
    128	mask = GENMASK(mmio_regs[ret].shift + mmio_regs[ret].bits - 1, mmio_regs[ret].shift);\
    129	reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
    130	reg_val &= ~mask;\
    131	reg_val |= (input << mmio_regs[ret].shift);\
    132	writel(reg_val, (void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
    133	return count;\
    134}
    135
    136RFIM_SHOW(vco_ref_code_lo, 0)
    137RFIM_SHOW(vco_ref_code_hi, 0)
    138RFIM_SHOW(spread_spectrum_pct, 0)
    139RFIM_SHOW(spread_spectrum_clk_enable, 0)
    140RFIM_SHOW(rfi_vco_ref_code, 0)
    141RFIM_SHOW(fivr_fffc_rev, 0)
    142
    143RFIM_STORE(vco_ref_code_lo, 0)
    144RFIM_STORE(vco_ref_code_hi, 0)
    145RFIM_STORE(spread_spectrum_pct, 0)
    146RFIM_STORE(spread_spectrum_clk_enable, 0)
    147RFIM_STORE(rfi_vco_ref_code, 0)
    148RFIM_STORE(fivr_fffc_rev, 0)
    149
    150static DEVICE_ATTR_RW(vco_ref_code_lo);
    151static DEVICE_ATTR_RW(vco_ref_code_hi);
    152static DEVICE_ATTR_RW(spread_spectrum_pct);
    153static DEVICE_ATTR_RW(spread_spectrum_clk_enable);
    154static DEVICE_ATTR_RW(rfi_vco_ref_code);
    155static DEVICE_ATTR_RW(fivr_fffc_rev);
    156
    157static struct attribute *fivr_attrs[] = {
    158	&dev_attr_vco_ref_code_lo.attr,
    159	&dev_attr_vco_ref_code_hi.attr,
    160	&dev_attr_spread_spectrum_pct.attr,
    161	&dev_attr_spread_spectrum_clk_enable.attr,
    162	&dev_attr_rfi_vco_ref_code.attr,
    163	&dev_attr_fivr_fffc_rev.attr,
    164	NULL
    165};
    166
    167static const struct attribute_group fivr_attribute_group = {
    168	.attrs = fivr_attrs,
    169	.name = "fivr"
    170};
    171
    172RFIM_SHOW(rfi_restriction_run_busy, 1)
    173RFIM_SHOW(rfi_restriction_err_code, 1)
    174RFIM_SHOW(rfi_restriction_data_rate, 1)
    175RFIM_SHOW(ddr_data_rate_point_0, 1)
    176RFIM_SHOW(ddr_data_rate_point_1, 1)
    177RFIM_SHOW(ddr_data_rate_point_2, 1)
    178RFIM_SHOW(ddr_data_rate_point_3, 1)
    179RFIM_SHOW(rfi_disable, 1)
    180
    181RFIM_STORE(rfi_restriction_run_busy, 1)
    182RFIM_STORE(rfi_restriction_err_code, 1)
    183RFIM_STORE(rfi_restriction_data_rate, 1)
    184RFIM_STORE(rfi_disable, 1)
    185
    186static DEVICE_ATTR_RW(rfi_restriction_run_busy);
    187static DEVICE_ATTR_RW(rfi_restriction_err_code);
    188static DEVICE_ATTR_RW(rfi_restriction_data_rate);
    189static DEVICE_ATTR_RO(ddr_data_rate_point_0);
    190static DEVICE_ATTR_RO(ddr_data_rate_point_1);
    191static DEVICE_ATTR_RO(ddr_data_rate_point_2);
    192static DEVICE_ATTR_RO(ddr_data_rate_point_3);
    193static DEVICE_ATTR_RW(rfi_disable);
    194
    195static ssize_t rfi_restriction_store(struct device *dev,
    196				     struct device_attribute *attr,
    197				     const char *buf, size_t count)
    198{
    199	u16 id = 0x0008;
    200	u32 input;
    201	int ret;
    202
    203	ret = kstrtou32(buf, 10, &input);
    204	if (ret)
    205		return ret;
    206
    207	ret = processor_thermal_send_mbox_write_cmd(to_pci_dev(dev), id, input);
    208	if (ret)
    209		return ret;
    210
    211	return count;
    212}
    213
    214static ssize_t rfi_restriction_show(struct device *dev,
    215				    struct device_attribute *attr,
    216				    char *buf)
    217{
    218	u16 id = 0x0007;
    219	u64 resp;
    220	int ret;
    221
    222	ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp);
    223	if (ret)
    224		return ret;
    225
    226	return sprintf(buf, "%llu\n", resp);
    227}
    228
    229static ssize_t ddr_data_rate_show(struct device *dev,
    230				  struct device_attribute *attr,
    231				  char *buf)
    232{
    233	u16 id = 0x0107;
    234	u64 resp;
    235	int ret;
    236
    237	ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp);
    238	if (ret)
    239		return ret;
    240
    241	return sprintf(buf, "%llu\n", resp);
    242}
    243
    244static DEVICE_ATTR_RW(rfi_restriction);
    245static DEVICE_ATTR_RO(ddr_data_rate);
    246
    247static struct attribute *dvfs_attrs[] = {
    248	&dev_attr_rfi_restriction_run_busy.attr,
    249	&dev_attr_rfi_restriction_err_code.attr,
    250	&dev_attr_rfi_restriction_data_rate.attr,
    251	&dev_attr_ddr_data_rate_point_0.attr,
    252	&dev_attr_ddr_data_rate_point_1.attr,
    253	&dev_attr_ddr_data_rate_point_2.attr,
    254	&dev_attr_ddr_data_rate_point_3.attr,
    255	&dev_attr_rfi_disable.attr,
    256	&dev_attr_ddr_data_rate.attr,
    257	&dev_attr_rfi_restriction.attr,
    258	NULL
    259};
    260
    261static const struct attribute_group dvfs_attribute_group = {
    262	.attrs = dvfs_attrs,
    263	.name = "dvfs"
    264};
    265
    266int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
    267{
    268	int ret;
    269
    270	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) {
    271		ret = sysfs_create_group(&pdev->dev.kobj, &fivr_attribute_group);
    272		if (ret)
    273			return ret;
    274	}
    275
    276	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) {
    277		ret = sysfs_create_group(&pdev->dev.kobj, &dvfs_attribute_group);
    278		if (ret && proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) {
    279			sysfs_remove_group(&pdev->dev.kobj, &fivr_attribute_group);
    280			return ret;
    281		}
    282	}
    283
    284	return 0;
    285}
    286EXPORT_SYMBOL_GPL(proc_thermal_rfim_add);
    287
    288void proc_thermal_rfim_remove(struct pci_dev *pdev)
    289{
    290	struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev);
    291
    292	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR)
    293		sysfs_remove_group(&pdev->dev.kobj, &fivr_attribute_group);
    294
    295	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS)
    296		sysfs_remove_group(&pdev->dev.kobj, &dvfs_attribute_group);
    297}
    298EXPORT_SYMBOL_GPL(proc_thermal_rfim_remove);
    299
    300MODULE_LICENSE("GPL v2");