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

kdebugfs.c (3914B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Architecture specific debugfs files
      4 *
      5 * Copyright (C) 2007, Intel Corp.
      6 *	Huang Ying <ying.huang@intel.com>
      7 */
      8#include <linux/debugfs.h>
      9#include <linux/uaccess.h>
     10#include <linux/export.h>
     11#include <linux/slab.h>
     12#include <linux/init.h>
     13#include <linux/stat.h>
     14#include <linux/io.h>
     15#include <linux/mm.h>
     16
     17#include <asm/setup.h>
     18
     19struct dentry *arch_debugfs_dir;
     20EXPORT_SYMBOL(arch_debugfs_dir);
     21
     22#ifdef CONFIG_DEBUG_BOOT_PARAMS
     23struct setup_data_node {
     24	u64 paddr;
     25	u32 type;
     26	u32 len;
     27};
     28
     29static ssize_t setup_data_read(struct file *file, char __user *user_buf,
     30			       size_t count, loff_t *ppos)
     31{
     32	struct setup_data_node *node = file->private_data;
     33	unsigned long remain;
     34	loff_t pos = *ppos;
     35	void *p;
     36	u64 pa;
     37
     38	if (pos < 0)
     39		return -EINVAL;
     40
     41	if (pos >= node->len)
     42		return 0;
     43
     44	if (count > node->len - pos)
     45		count = node->len - pos;
     46
     47	pa = node->paddr + pos;
     48
     49	/* Is it direct data or invalid indirect one? */
     50	if (!(node->type & SETUP_INDIRECT) || node->type == SETUP_INDIRECT)
     51		pa += sizeof(struct setup_data);
     52
     53	p = memremap(pa, count, MEMREMAP_WB);
     54	if (!p)
     55		return -ENOMEM;
     56
     57	remain = copy_to_user(user_buf, p, count);
     58
     59	memunmap(p);
     60
     61	if (remain)
     62		return -EFAULT;
     63
     64	*ppos = pos + count;
     65
     66	return count;
     67}
     68
     69static const struct file_operations fops_setup_data = {
     70	.read		= setup_data_read,
     71	.open		= simple_open,
     72	.llseek		= default_llseek,
     73};
     74
     75static void __init
     76create_setup_data_node(struct dentry *parent, int no,
     77		       struct setup_data_node *node)
     78{
     79	struct dentry *d;
     80	char buf[16];
     81
     82	sprintf(buf, "%d", no);
     83	d = debugfs_create_dir(buf, parent);
     84
     85	debugfs_create_x32("type", S_IRUGO, d, &node->type);
     86	debugfs_create_file("data", S_IRUGO, d, node, &fops_setup_data);
     87}
     88
     89static int __init create_setup_data_nodes(struct dentry *parent)
     90{
     91	struct setup_indirect *indirect;
     92	struct setup_data_node *node;
     93	struct setup_data *data;
     94	u64 pa_data, pa_next;
     95	struct dentry *d;
     96	int error;
     97	u32 len;
     98	int no = 0;
     99
    100	d = debugfs_create_dir("setup_data", parent);
    101
    102	pa_data = boot_params.hdr.setup_data;
    103
    104	while (pa_data) {
    105		node = kmalloc(sizeof(*node), GFP_KERNEL);
    106		if (!node) {
    107			error = -ENOMEM;
    108			goto err_dir;
    109		}
    110
    111		data = memremap(pa_data, sizeof(*data), MEMREMAP_WB);
    112		if (!data) {
    113			kfree(node);
    114			error = -ENOMEM;
    115			goto err_dir;
    116		}
    117		pa_next = data->next;
    118
    119		if (data->type == SETUP_INDIRECT) {
    120			len = sizeof(*data) + data->len;
    121			memunmap(data);
    122			data = memremap(pa_data, len, MEMREMAP_WB);
    123			if (!data) {
    124				kfree(node);
    125				error = -ENOMEM;
    126				goto err_dir;
    127			}
    128
    129			indirect = (struct setup_indirect *)data->data;
    130
    131			if (indirect->type != SETUP_INDIRECT) {
    132				node->paddr = indirect->addr;
    133				node->type  = indirect->type;
    134				node->len   = indirect->len;
    135			} else {
    136				node->paddr = pa_data;
    137				node->type  = data->type;
    138				node->len   = data->len;
    139			}
    140		} else {
    141			node->paddr = pa_data;
    142			node->type  = data->type;
    143			node->len   = data->len;
    144		}
    145
    146		create_setup_data_node(d, no, node);
    147		pa_data = pa_next;
    148
    149		memunmap(data);
    150		no++;
    151	}
    152
    153	return 0;
    154
    155err_dir:
    156	debugfs_remove_recursive(d);
    157	return error;
    158}
    159
    160static struct debugfs_blob_wrapper boot_params_blob = {
    161	.data		= &boot_params,
    162	.size		= sizeof(boot_params),
    163};
    164
    165static int __init boot_params_kdebugfs_init(void)
    166{
    167	struct dentry *dbp;
    168	int error;
    169
    170	dbp = debugfs_create_dir("boot_params", arch_debugfs_dir);
    171
    172	debugfs_create_x16("version", S_IRUGO, dbp, &boot_params.hdr.version);
    173	debugfs_create_blob("data", S_IRUGO, dbp, &boot_params_blob);
    174
    175	error = create_setup_data_nodes(dbp);
    176	if (error)
    177		debugfs_remove_recursive(dbp);
    178
    179	return error;
    180}
    181#endif /* CONFIG_DEBUG_BOOT_PARAMS */
    182
    183static int __init arch_kdebugfs_init(void)
    184{
    185	int error = 0;
    186
    187	arch_debugfs_dir = debugfs_create_dir("x86", NULL);
    188
    189#ifdef CONFIG_DEBUG_BOOT_PARAMS
    190	error = boot_params_kdebugfs_init();
    191#endif
    192
    193	return error;
    194}
    195arch_initcall(arch_kdebugfs_init);