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

debugfs.c (11509B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
      4 *
      5 */
      6
      7#include <linux/debugfs.h>
      8#include <linux/device.h>
      9#include <linux/interrupt.h>
     10#include <linux/list.h>
     11#include <linux/mhi.h>
     12#include <linux/module.h>
     13#include "internal.h"
     14
     15static int mhi_debugfs_states_show(struct seq_file *m, void *d)
     16{
     17	struct mhi_controller *mhi_cntrl = m->private;
     18
     19	/* states */
     20	seq_printf(m, "PM state: %s Device: %s MHI state: %s EE: %s wake: %s\n",
     21		   to_mhi_pm_state_str(mhi_cntrl->pm_state),
     22		   mhi_is_active(mhi_cntrl) ? "Active" : "Inactive",
     23		   mhi_state_str(mhi_cntrl->dev_state),
     24		   TO_MHI_EXEC_STR(mhi_cntrl->ee),
     25		   mhi_cntrl->wake_set ? "true" : "false");
     26
     27	/* counters */
     28	seq_printf(m, "M0: %u M2: %u M3: %u", mhi_cntrl->M0, mhi_cntrl->M2,
     29		   mhi_cntrl->M3);
     30
     31	seq_printf(m, " device wake: %u pending packets: %u\n",
     32		   atomic_read(&mhi_cntrl->dev_wake),
     33		   atomic_read(&mhi_cntrl->pending_pkts));
     34
     35	return 0;
     36}
     37
     38static int mhi_debugfs_events_show(struct seq_file *m, void *d)
     39{
     40	struct mhi_controller *mhi_cntrl = m->private;
     41	struct mhi_event *mhi_event;
     42	struct mhi_event_ctxt *er_ctxt;
     43	int i;
     44
     45	if (!mhi_is_active(mhi_cntrl)) {
     46		seq_puts(m, "Device not ready\n");
     47		return -ENODEV;
     48	}
     49
     50	er_ctxt = mhi_cntrl->mhi_ctxt->er_ctxt;
     51	mhi_event = mhi_cntrl->mhi_event;
     52	for (i = 0; i < mhi_cntrl->total_ev_rings;
     53						i++, er_ctxt++, mhi_event++) {
     54		struct mhi_ring *ring = &mhi_event->ring;
     55
     56		if (mhi_event->offload_ev) {
     57			seq_printf(m, "Index: %d is an offload event ring\n",
     58				   i);
     59			continue;
     60		}
     61
     62		seq_printf(m, "Index: %d intmod count: %lu time: %lu",
     63			   i, (le32_to_cpu(er_ctxt->intmod) & EV_CTX_INTMODC_MASK) >>
     64			   __ffs(EV_CTX_INTMODC_MASK),
     65			   (le32_to_cpu(er_ctxt->intmod) & EV_CTX_INTMODT_MASK) >>
     66			   __ffs(EV_CTX_INTMODT_MASK));
     67
     68		seq_printf(m, " base: 0x%0llx len: 0x%llx", le64_to_cpu(er_ctxt->rbase),
     69			   le64_to_cpu(er_ctxt->rlen));
     70
     71		seq_printf(m, " rp: 0x%llx wp: 0x%llx", le64_to_cpu(er_ctxt->rp),
     72			   le64_to_cpu(er_ctxt->wp));
     73
     74		seq_printf(m, " local rp: 0x%pK db: 0x%pad\n", ring->rp,
     75			   &mhi_event->db_cfg.db_val);
     76	}
     77
     78	return 0;
     79}
     80
     81static int mhi_debugfs_channels_show(struct seq_file *m, void *d)
     82{
     83	struct mhi_controller *mhi_cntrl = m->private;
     84	struct mhi_chan *mhi_chan;
     85	struct mhi_chan_ctxt *chan_ctxt;
     86	int i;
     87
     88	if (!mhi_is_active(mhi_cntrl)) {
     89		seq_puts(m, "Device not ready\n");
     90		return -ENODEV;
     91	}
     92
     93	mhi_chan = mhi_cntrl->mhi_chan;
     94	chan_ctxt = mhi_cntrl->mhi_ctxt->chan_ctxt;
     95	for (i = 0; i < mhi_cntrl->max_chan; i++, chan_ctxt++, mhi_chan++) {
     96		struct mhi_ring *ring = &mhi_chan->tre_ring;
     97
     98		if (mhi_chan->offload_ch) {
     99			seq_printf(m, "%s(%u) is an offload channel\n",
    100				   mhi_chan->name, mhi_chan->chan);
    101			continue;
    102		}
    103
    104		if (!mhi_chan->mhi_dev)
    105			continue;
    106
    107		seq_printf(m,
    108			   "%s(%u) state: 0x%lx brstmode: 0x%lx pollcfg: 0x%lx",
    109			   mhi_chan->name, mhi_chan->chan, (le32_to_cpu(chan_ctxt->chcfg) &
    110			   CHAN_CTX_CHSTATE_MASK) >> __ffs(CHAN_CTX_CHSTATE_MASK),
    111			   (le32_to_cpu(chan_ctxt->chcfg) & CHAN_CTX_BRSTMODE_MASK) >>
    112			   __ffs(CHAN_CTX_BRSTMODE_MASK), (le32_to_cpu(chan_ctxt->chcfg) &
    113			   CHAN_CTX_POLLCFG_MASK) >> __ffs(CHAN_CTX_POLLCFG_MASK));
    114
    115		seq_printf(m, " type: 0x%x event ring: %u", le32_to_cpu(chan_ctxt->chtype),
    116			   le32_to_cpu(chan_ctxt->erindex));
    117
    118		seq_printf(m, " base: 0x%llx len: 0x%llx rp: 0x%llx wp: 0x%llx",
    119			   le64_to_cpu(chan_ctxt->rbase), le64_to_cpu(chan_ctxt->rlen),
    120			   le64_to_cpu(chan_ctxt->rp), le64_to_cpu(chan_ctxt->wp));
    121
    122		seq_printf(m, " local rp: 0x%pK local wp: 0x%pK db: 0x%pad\n",
    123			   ring->rp, ring->wp,
    124			   &mhi_chan->db_cfg.db_val);
    125	}
    126
    127	return 0;
    128}
    129
    130static int mhi_device_info_show(struct device *dev, void *data)
    131{
    132	struct mhi_device *mhi_dev;
    133
    134	if (dev->bus != &mhi_bus_type)
    135		return 0;
    136
    137	mhi_dev = to_mhi_device(dev);
    138
    139	seq_printf((struct seq_file *)data, "%s: type: %s dev_wake: %u",
    140		   mhi_dev->name, mhi_dev->dev_type ? "Controller" : "Transfer",
    141		   mhi_dev->dev_wake);
    142
    143	/* for transfer device types only */
    144	if (mhi_dev->dev_type == MHI_DEVICE_XFER)
    145		seq_printf((struct seq_file *)data, " channels: %u(UL)/%u(DL)",
    146			   mhi_dev->ul_chan_id, mhi_dev->dl_chan_id);
    147
    148	seq_puts((struct seq_file *)data, "\n");
    149
    150	return 0;
    151}
    152
    153static int mhi_debugfs_devices_show(struct seq_file *m, void *d)
    154{
    155	struct mhi_controller *mhi_cntrl = m->private;
    156
    157	if (!mhi_is_active(mhi_cntrl)) {
    158		seq_puts(m, "Device not ready\n");
    159		return -ENODEV;
    160	}
    161
    162	/* Show controller and client(s) info */
    163	mhi_device_info_show(&mhi_cntrl->mhi_dev->dev, m);
    164	device_for_each_child(&mhi_cntrl->mhi_dev->dev, m, mhi_device_info_show);
    165
    166	return 0;
    167}
    168
    169static int mhi_debugfs_regdump_show(struct seq_file *m, void *d)
    170{
    171	struct mhi_controller *mhi_cntrl = m->private;
    172	enum mhi_state state;
    173	enum mhi_ee_type ee;
    174	int i, ret = -EIO;
    175	u32 val;
    176	void __iomem *mhi_base = mhi_cntrl->regs;
    177	void __iomem *bhi_base = mhi_cntrl->bhi;
    178	void __iomem *bhie_base = mhi_cntrl->bhie;
    179	void __iomem *wake_db = mhi_cntrl->wake_db;
    180	struct {
    181		const char *name;
    182		int offset;
    183		void __iomem *base;
    184	} regs[] = {
    185		{ "MHI_REGLEN", MHIREGLEN, mhi_base},
    186		{ "MHI_VER", MHIVER, mhi_base},
    187		{ "MHI_CFG", MHICFG, mhi_base},
    188		{ "MHI_CTRL", MHICTRL, mhi_base},
    189		{ "MHI_STATUS", MHISTATUS, mhi_base},
    190		{ "MHI_WAKE_DB", 0, wake_db},
    191		{ "BHI_EXECENV", BHI_EXECENV, bhi_base},
    192		{ "BHI_STATUS", BHI_STATUS, bhi_base},
    193		{ "BHI_ERRCODE", BHI_ERRCODE, bhi_base},
    194		{ "BHI_ERRDBG1", BHI_ERRDBG1, bhi_base},
    195		{ "BHI_ERRDBG2", BHI_ERRDBG2, bhi_base},
    196		{ "BHI_ERRDBG3", BHI_ERRDBG3, bhi_base},
    197		{ "BHIE_TXVEC_DB", BHIE_TXVECDB_OFFS, bhie_base},
    198		{ "BHIE_TXVEC_STATUS", BHIE_TXVECSTATUS_OFFS, bhie_base},
    199		{ "BHIE_RXVEC_DB", BHIE_RXVECDB_OFFS, bhie_base},
    200		{ "BHIE_RXVEC_STATUS", BHIE_RXVECSTATUS_OFFS, bhie_base},
    201		{ NULL },
    202	};
    203
    204	if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state))
    205		return ret;
    206
    207	seq_printf(m, "Host PM state: %s Device state: %s EE: %s\n",
    208		   to_mhi_pm_state_str(mhi_cntrl->pm_state),
    209		   mhi_state_str(mhi_cntrl->dev_state),
    210		   TO_MHI_EXEC_STR(mhi_cntrl->ee));
    211
    212	state = mhi_get_mhi_state(mhi_cntrl);
    213	ee = mhi_get_exec_env(mhi_cntrl);
    214	seq_printf(m, "Device EE: %s state: %s\n", TO_MHI_EXEC_STR(ee),
    215		   mhi_state_str(state));
    216
    217	for (i = 0; regs[i].name; i++) {
    218		if (!regs[i].base)
    219			continue;
    220		ret = mhi_read_reg(mhi_cntrl, regs[i].base, regs[i].offset,
    221				   &val);
    222		if (ret)
    223			continue;
    224
    225		seq_printf(m, "%s: 0x%x\n", regs[i].name, val);
    226	}
    227
    228	return 0;
    229}
    230
    231static int mhi_debugfs_device_wake_show(struct seq_file *m, void *d)
    232{
    233	struct mhi_controller *mhi_cntrl = m->private;
    234	struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev;
    235
    236	if (!mhi_is_active(mhi_cntrl)) {
    237		seq_puts(m, "Device not ready\n");
    238		return -ENODEV;
    239	}
    240
    241	seq_printf(m,
    242		   "Wake count: %d\n%s\n", mhi_dev->dev_wake,
    243		   "Usage: echo get/put > device_wake to vote/unvote for M0");
    244
    245	return 0;
    246}
    247
    248static ssize_t mhi_debugfs_device_wake_write(struct file *file,
    249					     const char __user *ubuf,
    250					     size_t count, loff_t *ppos)
    251{
    252	struct seq_file	*m = file->private_data;
    253	struct mhi_controller *mhi_cntrl = m->private;
    254	struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev;
    255	char buf[16];
    256	int ret = -EINVAL;
    257
    258	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
    259		return -EFAULT;
    260
    261	if (!strncmp(buf, "get", 3)) {
    262		ret = mhi_device_get_sync(mhi_dev);
    263	} else if (!strncmp(buf, "put", 3)) {
    264		mhi_device_put(mhi_dev);
    265		ret = 0;
    266	}
    267
    268	return ret ? ret : count;
    269}
    270
    271static int mhi_debugfs_timeout_ms_show(struct seq_file *m, void *d)
    272{
    273	struct mhi_controller *mhi_cntrl = m->private;
    274
    275	seq_printf(m, "%u ms\n", mhi_cntrl->timeout_ms);
    276
    277	return 0;
    278}
    279
    280static ssize_t mhi_debugfs_timeout_ms_write(struct file *file,
    281					    const char __user *ubuf,
    282					    size_t count, loff_t *ppos)
    283{
    284	struct seq_file	*m = file->private_data;
    285	struct mhi_controller *mhi_cntrl = m->private;
    286	u32 timeout_ms;
    287
    288	if (kstrtou32_from_user(ubuf, count, 0, &timeout_ms))
    289		return -EINVAL;
    290
    291	mhi_cntrl->timeout_ms = timeout_ms;
    292
    293	return count;
    294}
    295
    296static int mhi_debugfs_states_open(struct inode *inode, struct file *fp)
    297{
    298	return single_open(fp, mhi_debugfs_states_show, inode->i_private);
    299}
    300
    301static int mhi_debugfs_events_open(struct inode *inode, struct file *fp)
    302{
    303	return single_open(fp, mhi_debugfs_events_show, inode->i_private);
    304}
    305
    306static int mhi_debugfs_channels_open(struct inode *inode, struct file *fp)
    307{
    308	return single_open(fp, mhi_debugfs_channels_show, inode->i_private);
    309}
    310
    311static int mhi_debugfs_devices_open(struct inode *inode, struct file *fp)
    312{
    313	return single_open(fp, mhi_debugfs_devices_show, inode->i_private);
    314}
    315
    316static int mhi_debugfs_regdump_open(struct inode *inode, struct file *fp)
    317{
    318	return single_open(fp, mhi_debugfs_regdump_show, inode->i_private);
    319}
    320
    321static int mhi_debugfs_device_wake_open(struct inode *inode, struct file *fp)
    322{
    323	return single_open(fp, mhi_debugfs_device_wake_show, inode->i_private);
    324}
    325
    326static int mhi_debugfs_timeout_ms_open(struct inode *inode, struct file *fp)
    327{
    328	return single_open(fp, mhi_debugfs_timeout_ms_show, inode->i_private);
    329}
    330
    331static const struct file_operations debugfs_states_fops = {
    332	.open = mhi_debugfs_states_open,
    333	.release = single_release,
    334	.read = seq_read,
    335};
    336
    337static const struct file_operations debugfs_events_fops = {
    338	.open = mhi_debugfs_events_open,
    339	.release = single_release,
    340	.read = seq_read,
    341};
    342
    343static const struct file_operations debugfs_channels_fops = {
    344	.open = mhi_debugfs_channels_open,
    345	.release = single_release,
    346	.read = seq_read,
    347};
    348
    349static const struct file_operations debugfs_devices_fops = {
    350	.open = mhi_debugfs_devices_open,
    351	.release = single_release,
    352	.read = seq_read,
    353};
    354
    355static const struct file_operations debugfs_regdump_fops = {
    356	.open = mhi_debugfs_regdump_open,
    357	.release = single_release,
    358	.read = seq_read,
    359};
    360
    361static const struct file_operations debugfs_device_wake_fops = {
    362	.open = mhi_debugfs_device_wake_open,
    363	.write = mhi_debugfs_device_wake_write,
    364	.release = single_release,
    365	.read = seq_read,
    366};
    367
    368static const struct file_operations debugfs_timeout_ms_fops = {
    369	.open = mhi_debugfs_timeout_ms_open,
    370	.write = mhi_debugfs_timeout_ms_write,
    371	.release = single_release,
    372	.read = seq_read,
    373};
    374
    375static struct dentry *mhi_debugfs_root;
    376
    377void mhi_create_debugfs(struct mhi_controller *mhi_cntrl)
    378{
    379	mhi_cntrl->debugfs_dentry =
    380			debugfs_create_dir(dev_name(&mhi_cntrl->mhi_dev->dev),
    381					   mhi_debugfs_root);
    382
    383	debugfs_create_file("states", 0444, mhi_cntrl->debugfs_dentry,
    384			    mhi_cntrl, &debugfs_states_fops);
    385	debugfs_create_file("events", 0444, mhi_cntrl->debugfs_dentry,
    386			    mhi_cntrl, &debugfs_events_fops);
    387	debugfs_create_file("channels", 0444, mhi_cntrl->debugfs_dentry,
    388			    mhi_cntrl, &debugfs_channels_fops);
    389	debugfs_create_file("devices", 0444, mhi_cntrl->debugfs_dentry,
    390			    mhi_cntrl, &debugfs_devices_fops);
    391	debugfs_create_file("regdump", 0444, mhi_cntrl->debugfs_dentry,
    392			    mhi_cntrl, &debugfs_regdump_fops);
    393	debugfs_create_file("device_wake", 0644, mhi_cntrl->debugfs_dentry,
    394			    mhi_cntrl, &debugfs_device_wake_fops);
    395	debugfs_create_file("timeout_ms", 0644, mhi_cntrl->debugfs_dentry,
    396			    mhi_cntrl, &debugfs_timeout_ms_fops);
    397}
    398
    399void mhi_destroy_debugfs(struct mhi_controller *mhi_cntrl)
    400{
    401	debugfs_remove_recursive(mhi_cntrl->debugfs_dentry);
    402	mhi_cntrl->debugfs_dentry = NULL;
    403}
    404
    405void mhi_debugfs_init(void)
    406{
    407	mhi_debugfs_root = debugfs_create_dir(mhi_bus_type.name, NULL);
    408}
    409
    410void mhi_debugfs_exit(void)
    411{
    412	debugfs_remove_recursive(mhi_debugfs_root);
    413}