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

pci_debug.c (4781B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *  Copyright IBM Corp. 2012,2015
      4 *
      5 *  Author(s):
      6 *    Jan Glauber <jang@linux.vnet.ibm.com>
      7 */
      8
      9#define KMSG_COMPONENT "zpci"
     10#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
     11
     12#include <linux/kernel.h>
     13#include <linux/seq_file.h>
     14#include <linux/debugfs.h>
     15#include <linux/export.h>
     16#include <linux/pci.h>
     17#include <asm/debug.h>
     18
     19#include <asm/pci_dma.h>
     20
     21static struct dentry *debugfs_root;
     22debug_info_t *pci_debug_msg_id;
     23EXPORT_SYMBOL_GPL(pci_debug_msg_id);
     24debug_info_t *pci_debug_err_id;
     25EXPORT_SYMBOL_GPL(pci_debug_err_id);
     26
     27static char *pci_common_names[] = {
     28	"Load operations",
     29	"Store operations",
     30	"Store block operations",
     31	"Refresh operations",
     32};
     33
     34static char *pci_fmt0_names[] = {
     35	"DMA read bytes",
     36	"DMA write bytes",
     37};
     38
     39static char *pci_fmt1_names[] = {
     40	"Received bytes",
     41	"Received packets",
     42	"Transmitted bytes",
     43	"Transmitted packets",
     44};
     45
     46static char *pci_fmt2_names[] = {
     47	"Consumed work units",
     48	"Maximum work units",
     49};
     50
     51static char *pci_fmt3_names[] = {
     52	"Transmitted bytes",
     53};
     54
     55static char *pci_sw_names[] = {
     56	"Allocated pages",
     57	"Mapped pages",
     58	"Unmapped pages",
     59};
     60
     61static void pci_fmb_show(struct seq_file *m, char *name[], int length,
     62			 u64 *data)
     63{
     64	int i;
     65
     66	for (i = 0; i < length; i++, data++)
     67		seq_printf(m, "%26s:\t%llu\n", name[i], *data);
     68}
     69
     70static void pci_sw_counter_show(struct seq_file *m)
     71{
     72	struct zpci_dev *zdev = m->private;
     73	atomic64_t *counter = &zdev->allocated_pages;
     74	int i;
     75
     76	for (i = 0; i < ARRAY_SIZE(pci_sw_names); i++, counter++)
     77		seq_printf(m, "%26s:\t%llu\n", pci_sw_names[i],
     78			   atomic64_read(counter));
     79}
     80
     81static int pci_perf_show(struct seq_file *m, void *v)
     82{
     83	struct zpci_dev *zdev = m->private;
     84
     85	if (!zdev)
     86		return 0;
     87
     88	mutex_lock(&zdev->lock);
     89	if (!zdev->fmb) {
     90		mutex_unlock(&zdev->lock);
     91		seq_puts(m, "FMB statistics disabled\n");
     92		return 0;
     93	}
     94
     95	/* header */
     96	seq_printf(m, "Update interval: %u ms\n", zdev->fmb_update);
     97	seq_printf(m, "Samples: %u\n", zdev->fmb->samples);
     98	seq_printf(m, "Last update TOD: %Lx\n", zdev->fmb->last_update);
     99
    100	pci_fmb_show(m, pci_common_names, ARRAY_SIZE(pci_common_names),
    101		     &zdev->fmb->ld_ops);
    102
    103	switch (zdev->fmb->format) {
    104	case 0:
    105		if (!(zdev->fmb->fmt_ind & ZPCI_FMB_DMA_COUNTER_VALID))
    106			break;
    107		pci_fmb_show(m, pci_fmt0_names, ARRAY_SIZE(pci_fmt0_names),
    108			     &zdev->fmb->fmt0.dma_rbytes);
    109		break;
    110	case 1:
    111		pci_fmb_show(m, pci_fmt1_names, ARRAY_SIZE(pci_fmt1_names),
    112			     &zdev->fmb->fmt1.rx_bytes);
    113		break;
    114	case 2:
    115		pci_fmb_show(m, pci_fmt2_names, ARRAY_SIZE(pci_fmt2_names),
    116			     &zdev->fmb->fmt2.consumed_work_units);
    117		break;
    118	case 3:
    119		pci_fmb_show(m, pci_fmt3_names, ARRAY_SIZE(pci_fmt3_names),
    120			     &zdev->fmb->fmt3.tx_bytes);
    121		break;
    122	default:
    123		seq_puts(m, "Unknown format\n");
    124	}
    125
    126	pci_sw_counter_show(m);
    127	mutex_unlock(&zdev->lock);
    128	return 0;
    129}
    130
    131static ssize_t pci_perf_seq_write(struct file *file, const char __user *ubuf,
    132				  size_t count, loff_t *off)
    133{
    134	struct zpci_dev *zdev = ((struct seq_file *) file->private_data)->private;
    135	unsigned long val;
    136	int rc;
    137
    138	if (!zdev)
    139		return 0;
    140
    141	rc = kstrtoul_from_user(ubuf, count, 10, &val);
    142	if (rc)
    143		return rc;
    144
    145	mutex_lock(&zdev->lock);
    146	switch (val) {
    147	case 0:
    148		rc = zpci_fmb_disable_device(zdev);
    149		break;
    150	case 1:
    151		rc = zpci_fmb_enable_device(zdev);
    152		break;
    153	}
    154	mutex_unlock(&zdev->lock);
    155	return rc ? rc : count;
    156}
    157
    158static int pci_perf_seq_open(struct inode *inode, struct file *filp)
    159{
    160	return single_open(filp, pci_perf_show,
    161			   file_inode(filp)->i_private);
    162}
    163
    164static const struct file_operations debugfs_pci_perf_fops = {
    165	.open	 = pci_perf_seq_open,
    166	.read	 = seq_read,
    167	.write	 = pci_perf_seq_write,
    168	.llseek  = seq_lseek,
    169	.release = single_release,
    170};
    171
    172void zpci_debug_init_device(struct zpci_dev *zdev, const char *name)
    173{
    174	zdev->debugfs_dev = debugfs_create_dir(name, debugfs_root);
    175
    176	debugfs_create_file("statistics", S_IFREG | S_IRUGO | S_IWUSR,
    177			    zdev->debugfs_dev, zdev, &debugfs_pci_perf_fops);
    178}
    179
    180void zpci_debug_exit_device(struct zpci_dev *zdev)
    181{
    182	debugfs_remove_recursive(zdev->debugfs_dev);
    183}
    184
    185int __init zpci_debug_init(void)
    186{
    187	/* event trace buffer */
    188	pci_debug_msg_id = debug_register("pci_msg", 8, 1, 8 * sizeof(long));
    189	if (!pci_debug_msg_id)
    190		return -EINVAL;
    191	debug_register_view(pci_debug_msg_id, &debug_sprintf_view);
    192	debug_set_level(pci_debug_msg_id, 3);
    193
    194	/* error log */
    195	pci_debug_err_id = debug_register("pci_error", 2, 1, 16);
    196	if (!pci_debug_err_id)
    197		return -EINVAL;
    198	debug_register_view(pci_debug_err_id, &debug_hex_ascii_view);
    199	debug_set_level(pci_debug_err_id, 3);
    200
    201	debugfs_root = debugfs_create_dir("pci", NULL);
    202	return 0;
    203}
    204
    205void zpci_debug_exit(void)
    206{
    207	debug_unregister(pci_debug_msg_id);
    208	debug_unregister(pci_debug_err_id);
    209	debugfs_remove(debugfs_root);
    210}