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

dfl-emif.c (5430B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * DFL device driver for EMIF private feature
      4 *
      5 * Copyright (C) 2020 Intel Corporation, Inc.
      6 *
      7 */
      8#include <linux/bitfield.h>
      9#include <linux/dfl.h>
     10#include <linux/errno.h>
     11#include <linux/io.h>
     12#include <linux/iopoll.h>
     13#include <linux/io-64-nonatomic-lo-hi.h>
     14#include <linux/kernel.h>
     15#include <linux/module.h>
     16#include <linux/spinlock.h>
     17#include <linux/types.h>
     18
     19#define FME_FEATURE_ID_EMIF		0x9
     20
     21#define EMIF_STAT			0x8
     22#define EMIF_STAT_INIT_DONE_SFT		0
     23#define EMIF_STAT_CALC_FAIL_SFT		8
     24#define EMIF_STAT_CLEAR_BUSY_SFT	16
     25#define EMIF_CTRL			0x10
     26#define EMIF_CTRL_CLEAR_EN_SFT		0
     27#define EMIF_CTRL_CLEAR_EN_MSK		GENMASK_ULL(3, 0)
     28
     29#define EMIF_POLL_INVL			10000 /* us */
     30#define EMIF_POLL_TIMEOUT		5000000 /* us */
     31
     32struct dfl_emif {
     33	struct device *dev;
     34	void __iomem *base;
     35	spinlock_t lock;	/* Serialises access to EMIF_CTRL reg */
     36};
     37
     38struct emif_attr {
     39	struct device_attribute attr;
     40	u32 shift;
     41	u32 index;
     42};
     43
     44#define to_emif_attr(dev_attr) \
     45	container_of(dev_attr, struct emif_attr, attr)
     46
     47static ssize_t emif_state_show(struct device *dev,
     48			       struct device_attribute *attr, char *buf)
     49{
     50	struct emif_attr *eattr = to_emif_attr(attr);
     51	struct dfl_emif *de = dev_get_drvdata(dev);
     52	u64 val;
     53
     54	val = readq(de->base + EMIF_STAT);
     55
     56	return sysfs_emit(buf, "%u\n",
     57			  !!(val & BIT_ULL(eattr->shift + eattr->index)));
     58}
     59
     60static ssize_t emif_clear_store(struct device *dev,
     61				struct device_attribute *attr,
     62				const char *buf, size_t count)
     63{
     64	struct emif_attr *eattr = to_emif_attr(attr);
     65	struct dfl_emif *de = dev_get_drvdata(dev);
     66	u64 clear_busy_msk, clear_en_msk, val;
     67	void __iomem *base = de->base;
     68
     69	if (!sysfs_streq(buf, "1"))
     70		return -EINVAL;
     71
     72	clear_busy_msk = BIT_ULL(EMIF_STAT_CLEAR_BUSY_SFT + eattr->index);
     73	clear_en_msk = BIT_ULL(EMIF_CTRL_CLEAR_EN_SFT + eattr->index);
     74
     75	spin_lock(&de->lock);
     76	/* The CLEAR_EN field is WO, but other fields are RW */
     77	val = readq(base + EMIF_CTRL);
     78	val &= ~EMIF_CTRL_CLEAR_EN_MSK;
     79	val |= clear_en_msk;
     80	writeq(val, base + EMIF_CTRL);
     81	spin_unlock(&de->lock);
     82
     83	if (readq_poll_timeout(base + EMIF_STAT, val,
     84			       !(val & clear_busy_msk),
     85			       EMIF_POLL_INVL, EMIF_POLL_TIMEOUT)) {
     86		dev_err(de->dev, "timeout, fail to clear\n");
     87		return -ETIMEDOUT;
     88	}
     89
     90	return count;
     91}
     92
     93#define emif_state_attr(_name, _shift, _index)				\
     94	static struct emif_attr emif_attr_##inf##_index##_##_name =	\
     95		{ .attr = __ATTR(inf##_index##_##_name, 0444,		\
     96				 emif_state_show, NULL),		\
     97		  .shift = (_shift), .index = (_index) }
     98
     99#define emif_clear_attr(_index)						\
    100	static struct emif_attr emif_attr_##inf##_index##_clear =	\
    101		{ .attr = __ATTR(inf##_index##_clear, 0200,		\
    102				 NULL, emif_clear_store),		\
    103		  .index = (_index) }
    104
    105emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 0);
    106emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 1);
    107emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 2);
    108emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 3);
    109
    110emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 0);
    111emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 1);
    112emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 2);
    113emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 3);
    114
    115emif_clear_attr(0);
    116emif_clear_attr(1);
    117emif_clear_attr(2);
    118emif_clear_attr(3);
    119
    120static struct attribute *dfl_emif_attrs[] = {
    121	&emif_attr_inf0_init_done.attr.attr,
    122	&emif_attr_inf0_cal_fail.attr.attr,
    123	&emif_attr_inf0_clear.attr.attr,
    124
    125	&emif_attr_inf1_init_done.attr.attr,
    126	&emif_attr_inf1_cal_fail.attr.attr,
    127	&emif_attr_inf1_clear.attr.attr,
    128
    129	&emif_attr_inf2_init_done.attr.attr,
    130	&emif_attr_inf2_cal_fail.attr.attr,
    131	&emif_attr_inf2_clear.attr.attr,
    132
    133	&emif_attr_inf3_init_done.attr.attr,
    134	&emif_attr_inf3_cal_fail.attr.attr,
    135	&emif_attr_inf3_clear.attr.attr,
    136
    137	NULL,
    138};
    139
    140static umode_t dfl_emif_visible(struct kobject *kobj,
    141				struct attribute *attr, int n)
    142{
    143	struct dfl_emif *de = dev_get_drvdata(kobj_to_dev(kobj));
    144	struct emif_attr *eattr = container_of(attr, struct emif_attr,
    145					       attr.attr);
    146	u64 val;
    147
    148	/*
    149	 * This device supports upto 4 memory interfaces, but not all
    150	 * interfaces are used on different platforms. The read out value of
    151	 * CLEAN_EN field (which is a bitmap) could tell how many interfaces
    152	 * are available.
    153	 */
    154	val = FIELD_GET(EMIF_CTRL_CLEAR_EN_MSK, readq(de->base + EMIF_CTRL));
    155
    156	return (val & BIT_ULL(eattr->index)) ? attr->mode : 0;
    157}
    158
    159static const struct attribute_group dfl_emif_group = {
    160	.is_visible = dfl_emif_visible,
    161	.attrs = dfl_emif_attrs,
    162};
    163
    164static const struct attribute_group *dfl_emif_groups[] = {
    165	&dfl_emif_group,
    166	NULL,
    167};
    168
    169static int dfl_emif_probe(struct dfl_device *ddev)
    170{
    171	struct device *dev = &ddev->dev;
    172	struct dfl_emif *de;
    173
    174	de = devm_kzalloc(dev, sizeof(*de), GFP_KERNEL);
    175	if (!de)
    176		return -ENOMEM;
    177
    178	de->base = devm_ioremap_resource(dev, &ddev->mmio_res);
    179	if (IS_ERR(de->base))
    180		return PTR_ERR(de->base);
    181
    182	de->dev = dev;
    183	spin_lock_init(&de->lock);
    184	dev_set_drvdata(dev, de);
    185
    186	return 0;
    187}
    188
    189static const struct dfl_device_id dfl_emif_ids[] = {
    190	{ FME_ID, FME_FEATURE_ID_EMIF },
    191	{ }
    192};
    193MODULE_DEVICE_TABLE(dfl, dfl_emif_ids);
    194
    195static struct dfl_driver dfl_emif_driver = {
    196	.drv	= {
    197		.name       = "dfl-emif",
    198		.dev_groups = dfl_emif_groups,
    199	},
    200	.id_table = dfl_emif_ids,
    201	.probe   = dfl_emif_probe,
    202};
    203module_dfl_driver(dfl_emif_driver);
    204
    205MODULE_DESCRIPTION("DFL EMIF driver");
    206MODULE_AUTHOR("Intel Corporation");
    207MODULE_LICENSE("GPL v2");