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

bpmp-debugfs.c (16698B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.
      4 */
      5#include <linux/debugfs.h>
      6#include <linux/dma-mapping.h>
      7#include <linux/slab.h>
      8#include <linux/uaccess.h>
      9
     10#include <soc/tegra/bpmp.h>
     11#include <soc/tegra/bpmp-abi.h>
     12
     13static DEFINE_MUTEX(bpmp_debug_lock);
     14
     15struct seqbuf {
     16	char *buf;
     17	size_t pos;
     18	size_t size;
     19};
     20
     21static void seqbuf_init(struct seqbuf *seqbuf, void *buf, size_t size)
     22{
     23	seqbuf->buf = buf;
     24	seqbuf->size = size;
     25	seqbuf->pos = 0;
     26}
     27
     28static size_t seqbuf_avail(struct seqbuf *seqbuf)
     29{
     30	return seqbuf->pos < seqbuf->size ? seqbuf->size - seqbuf->pos : 0;
     31}
     32
     33static size_t seqbuf_status(struct seqbuf *seqbuf)
     34{
     35	return seqbuf->pos <= seqbuf->size ? 0 : -EOVERFLOW;
     36}
     37
     38static int seqbuf_eof(struct seqbuf *seqbuf)
     39{
     40	return seqbuf->pos >= seqbuf->size;
     41}
     42
     43static int seqbuf_read(struct seqbuf *seqbuf, void *buf, size_t nbyte)
     44{
     45	nbyte = min(nbyte, seqbuf_avail(seqbuf));
     46	memcpy(buf, seqbuf->buf + seqbuf->pos, nbyte);
     47	seqbuf->pos += nbyte;
     48	return seqbuf_status(seqbuf);
     49}
     50
     51static int seqbuf_read_u32(struct seqbuf *seqbuf, uint32_t *v)
     52{
     53	int err;
     54
     55	err = seqbuf_read(seqbuf, v, 4);
     56	*v = le32_to_cpu(*v);
     57	return err;
     58}
     59
     60static int seqbuf_read_str(struct seqbuf *seqbuf, const char **str)
     61{
     62	*str = seqbuf->buf + seqbuf->pos;
     63	seqbuf->pos += strnlen(*str, seqbuf_avail(seqbuf));
     64	seqbuf->pos++;
     65	return seqbuf_status(seqbuf);
     66}
     67
     68static void seqbuf_seek(struct seqbuf *seqbuf, ssize_t offset)
     69{
     70	seqbuf->pos += offset;
     71}
     72
     73/* map filename in Linux debugfs to corresponding entry in BPMP */
     74static const char *get_filename(struct tegra_bpmp *bpmp,
     75				const struct file *file, char *buf, int size)
     76{
     77	const char *root_path, *filename = NULL;
     78	char *root_path_buf;
     79	size_t root_len;
     80	size_t root_path_buf_len = 512;
     81
     82	root_path_buf = kzalloc(root_path_buf_len, GFP_KERNEL);
     83	if (!root_path_buf)
     84		goto out;
     85
     86	root_path = dentry_path(bpmp->debugfs_mirror, root_path_buf,
     87				root_path_buf_len);
     88	if (IS_ERR(root_path))
     89		goto out;
     90
     91	root_len = strlen(root_path);
     92
     93	filename = dentry_path(file->f_path.dentry, buf, size);
     94	if (IS_ERR(filename)) {
     95		filename = NULL;
     96		goto out;
     97	}
     98
     99	if (strlen(filename) < root_len || strncmp(filename, root_path, root_len)) {
    100		filename = NULL;
    101		goto out;
    102	}
    103
    104	filename += root_len;
    105
    106out:
    107	kfree(root_path_buf);
    108	return filename;
    109}
    110
    111static int mrq_debug_open(struct tegra_bpmp *bpmp, const char *name,
    112			  uint32_t *fd, uint32_t *len, bool write)
    113{
    114	struct mrq_debug_request req = {
    115		.cmd = cpu_to_le32(write ? CMD_DEBUG_OPEN_WO : CMD_DEBUG_OPEN_RO),
    116	};
    117	struct mrq_debug_response resp;
    118	struct tegra_bpmp_message msg = {
    119		.mrq = MRQ_DEBUG,
    120		.tx = {
    121			.data = &req,
    122			.size = sizeof(req),
    123		},
    124		.rx = {
    125			.data = &resp,
    126			.size = sizeof(resp),
    127		},
    128	};
    129	ssize_t sz_name;
    130	int err = 0;
    131
    132	sz_name = strscpy(req.fop.name, name, sizeof(req.fop.name));
    133	if (sz_name < 0) {
    134		pr_err("File name too large: %s\n", name);
    135		return -EINVAL;
    136	}
    137
    138	err = tegra_bpmp_transfer(bpmp, &msg);
    139	if (err < 0)
    140		return err;
    141	else if (msg.rx.ret < 0)
    142		return -EINVAL;
    143
    144	*len = resp.fop.datalen;
    145	*fd = resp.fop.fd;
    146
    147	return 0;
    148}
    149
    150static int mrq_debug_close(struct tegra_bpmp *bpmp, uint32_t fd)
    151{
    152	struct mrq_debug_request req = {
    153		.cmd = cpu_to_le32(CMD_DEBUG_CLOSE),
    154		.frd = {
    155			.fd = fd,
    156		},
    157	};
    158	struct mrq_debug_response resp;
    159	struct tegra_bpmp_message msg = {
    160		.mrq = MRQ_DEBUG,
    161		.tx = {
    162			.data = &req,
    163			.size = sizeof(req),
    164		},
    165		.rx = {
    166			.data = &resp,
    167			.size = sizeof(resp),
    168		},
    169	};
    170	int err = 0;
    171
    172	err = tegra_bpmp_transfer(bpmp, &msg);
    173	if (err < 0)
    174		return err;
    175	else if (msg.rx.ret < 0)
    176		return -EINVAL;
    177
    178	return 0;
    179}
    180
    181static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name,
    182			  char *data, size_t sz_data, uint32_t *nbytes)
    183{
    184	struct mrq_debug_request req = {
    185		.cmd = cpu_to_le32(CMD_DEBUG_READ),
    186	};
    187	struct mrq_debug_response resp;
    188	struct tegra_bpmp_message msg = {
    189		.mrq = MRQ_DEBUG,
    190		.tx = {
    191			.data = &req,
    192			.size = sizeof(req),
    193		},
    194		.rx = {
    195			.data = &resp,
    196			.size = sizeof(resp),
    197		},
    198	};
    199	uint32_t fd = 0, len = 0;
    200	int remaining, err;
    201
    202	mutex_lock(&bpmp_debug_lock);
    203	err = mrq_debug_open(bpmp, name, &fd, &len, 0);
    204	if (err)
    205		goto out;
    206
    207	if (len > sz_data) {
    208		err = -EFBIG;
    209		goto close;
    210	}
    211
    212	req.frd.fd = fd;
    213	remaining = len;
    214
    215	while (remaining > 0) {
    216		err = tegra_bpmp_transfer(bpmp, &msg);
    217		if (err < 0) {
    218			goto close;
    219		} else if (msg.rx.ret < 0) {
    220			err = -EINVAL;
    221			goto close;
    222		}
    223
    224		if (resp.frd.readlen > remaining) {
    225			pr_err("%s: read data length invalid\n", __func__);
    226			err = -EINVAL;
    227			goto close;
    228		}
    229
    230		memcpy(data, resp.frd.data, resp.frd.readlen);
    231		data += resp.frd.readlen;
    232		remaining -= resp.frd.readlen;
    233	}
    234
    235	*nbytes = len;
    236
    237close:
    238	err = mrq_debug_close(bpmp, fd);
    239out:
    240	mutex_unlock(&bpmp_debug_lock);
    241	return err;
    242}
    243
    244static int mrq_debug_write(struct tegra_bpmp *bpmp, const char *name,
    245			   uint8_t *data, size_t sz_data)
    246{
    247	struct mrq_debug_request req = {
    248		.cmd = cpu_to_le32(CMD_DEBUG_WRITE)
    249	};
    250	struct mrq_debug_response resp;
    251	struct tegra_bpmp_message msg = {
    252		.mrq = MRQ_DEBUG,
    253		.tx = {
    254			.data = &req,
    255			.size = sizeof(req),
    256		},
    257		.rx = {
    258			.data = &resp,
    259			.size = sizeof(resp),
    260		},
    261	};
    262	uint32_t fd = 0, len = 0;
    263	size_t remaining;
    264	int err;
    265
    266	mutex_lock(&bpmp_debug_lock);
    267	err = mrq_debug_open(bpmp, name, &fd, &len, 1);
    268	if (err)
    269		goto out;
    270
    271	if (sz_data > len) {
    272		err = -EINVAL;
    273		goto close;
    274	}
    275
    276	req.fwr.fd = fd;
    277	remaining = sz_data;
    278
    279	while (remaining > 0) {
    280		len = min(remaining, sizeof(req.fwr.data));
    281		memcpy(req.fwr.data, data, len);
    282		req.fwr.datalen = len;
    283
    284		err = tegra_bpmp_transfer(bpmp, &msg);
    285		if (err < 0) {
    286			goto close;
    287		} else if (msg.rx.ret < 0) {
    288			err = -EINVAL;
    289			goto close;
    290		}
    291
    292		data += req.fwr.datalen;
    293		remaining -= req.fwr.datalen;
    294	}
    295
    296close:
    297	err = mrq_debug_close(bpmp, fd);
    298out:
    299	mutex_unlock(&bpmp_debug_lock);
    300	return err;
    301}
    302
    303static int bpmp_debug_show(struct seq_file *m, void *p)
    304{
    305	struct file *file = m->private;
    306	struct inode *inode = file_inode(file);
    307	struct tegra_bpmp *bpmp = inode->i_private;
    308	char fnamebuf[256];
    309	const char *filename;
    310	struct mrq_debug_request req = {
    311		.cmd = cpu_to_le32(CMD_DEBUG_READ),
    312	};
    313	struct mrq_debug_response resp;
    314	struct tegra_bpmp_message msg = {
    315		.mrq = MRQ_DEBUG,
    316		.tx = {
    317			.data = &req,
    318			.size = sizeof(req),
    319		},
    320		.rx = {
    321			.data = &resp,
    322			.size = sizeof(resp),
    323		},
    324	};
    325	uint32_t fd = 0, len = 0;
    326	int remaining, err;
    327
    328	filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
    329	if (!filename)
    330		return -ENOENT;
    331
    332	mutex_lock(&bpmp_debug_lock);
    333	err = mrq_debug_open(bpmp, filename, &fd, &len, 0);
    334	if (err)
    335		goto out;
    336
    337	req.frd.fd = fd;
    338	remaining = len;
    339
    340	while (remaining > 0) {
    341		err = tegra_bpmp_transfer(bpmp, &msg);
    342		if (err < 0) {
    343			goto close;
    344		} else if (msg.rx.ret < 0) {
    345			err = -EINVAL;
    346			goto close;
    347		}
    348
    349		if (resp.frd.readlen > remaining) {
    350			pr_err("%s: read data length invalid\n", __func__);
    351			err = -EINVAL;
    352			goto close;
    353		}
    354
    355		seq_write(m, resp.frd.data, resp.frd.readlen);
    356		remaining -= resp.frd.readlen;
    357	}
    358
    359close:
    360	err = mrq_debug_close(bpmp, fd);
    361out:
    362	mutex_unlock(&bpmp_debug_lock);
    363	return err;
    364}
    365
    366static ssize_t bpmp_debug_store(struct file *file, const char __user *buf,
    367		size_t count, loff_t *f_pos)
    368{
    369	struct inode *inode = file_inode(file);
    370	struct tegra_bpmp *bpmp = inode->i_private;
    371	char *databuf = NULL;
    372	char fnamebuf[256];
    373	const char *filename;
    374	ssize_t err;
    375
    376	filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
    377	if (!filename)
    378		return -ENOENT;
    379
    380	databuf = kmalloc(count, GFP_KERNEL);
    381	if (!databuf)
    382		return -ENOMEM;
    383
    384	if (copy_from_user(databuf, buf, count)) {
    385		err = -EFAULT;
    386		goto free_ret;
    387	}
    388
    389	err = mrq_debug_write(bpmp, filename, databuf, count);
    390
    391free_ret:
    392	kfree(databuf);
    393
    394	return err ?: count;
    395}
    396
    397static int bpmp_debug_open(struct inode *inode, struct file *file)
    398{
    399	return single_open_size(file, bpmp_debug_show, file, SZ_256K);
    400}
    401
    402static const struct file_operations bpmp_debug_fops = {
    403	.open		= bpmp_debug_open,
    404	.read		= seq_read,
    405	.llseek		= seq_lseek,
    406	.write		= bpmp_debug_store,
    407	.release	= single_release,
    408};
    409
    410static int bpmp_populate_debugfs_inband(struct tegra_bpmp *bpmp,
    411					struct dentry *parent,
    412					char *ppath)
    413{
    414	const size_t pathlen = SZ_256;
    415	const size_t bufsize = SZ_16K;
    416	uint32_t dsize, attrs = 0;
    417	struct dentry *dentry;
    418	struct seqbuf seqbuf;
    419	char *buf, *pathbuf;
    420	const char *name;
    421	int err = 0;
    422
    423	if (!bpmp || !parent || !ppath)
    424		return -EINVAL;
    425
    426	buf = kmalloc(bufsize, GFP_KERNEL);
    427	if (!buf)
    428		return -ENOMEM;
    429
    430	pathbuf = kzalloc(pathlen, GFP_KERNEL);
    431	if (!pathbuf) {
    432		kfree(buf);
    433		return -ENOMEM;
    434	}
    435
    436	err = mrq_debug_read(bpmp, ppath, buf, bufsize, &dsize);
    437	if (err)
    438		goto out;
    439
    440	seqbuf_init(&seqbuf, buf, dsize);
    441
    442	while (!seqbuf_eof(&seqbuf)) {
    443		err = seqbuf_read_u32(&seqbuf, &attrs);
    444		if (err)
    445			goto out;
    446
    447		err = seqbuf_read_str(&seqbuf, &name);
    448		if (err < 0)
    449			goto out;
    450
    451		if (attrs & DEBUGFS_S_ISDIR) {
    452			size_t len;
    453
    454			dentry = debugfs_create_dir(name, parent);
    455			if (IS_ERR(dentry)) {
    456				err = PTR_ERR(dentry);
    457				goto out;
    458			}
    459
    460			len = snprintf(pathbuf, pathlen, "%s%s/", ppath, name);
    461			if (len >= pathlen) {
    462				err = -EINVAL;
    463				goto out;
    464			}
    465
    466			err = bpmp_populate_debugfs_inband(bpmp, dentry,
    467							   pathbuf);
    468			if (err < 0)
    469				goto out;
    470		} else {
    471			umode_t mode;
    472
    473			mode = attrs & DEBUGFS_S_IRUSR ? 0400 : 0;
    474			mode |= attrs & DEBUGFS_S_IWUSR ? 0200 : 0;
    475			dentry = debugfs_create_file(name, mode, parent, bpmp,
    476						     &bpmp_debug_fops);
    477			if (!dentry) {
    478				err = -ENOMEM;
    479				goto out;
    480			}
    481		}
    482	}
    483
    484out:
    485	kfree(pathbuf);
    486	kfree(buf);
    487
    488	return err;
    489}
    490
    491static int mrq_debugfs_read(struct tegra_bpmp *bpmp,
    492			    dma_addr_t name, size_t sz_name,
    493			    dma_addr_t data, size_t sz_data,
    494			    size_t *nbytes)
    495{
    496	struct mrq_debugfs_request req = {
    497		.cmd = cpu_to_le32(CMD_DEBUGFS_READ),
    498		.fop = {
    499			.fnameaddr = cpu_to_le32((uint32_t)name),
    500			.fnamelen = cpu_to_le32((uint32_t)sz_name),
    501			.dataaddr = cpu_to_le32((uint32_t)data),
    502			.datalen = cpu_to_le32((uint32_t)sz_data),
    503		},
    504	};
    505	struct mrq_debugfs_response resp;
    506	struct tegra_bpmp_message msg = {
    507		.mrq = MRQ_DEBUGFS,
    508		.tx = {
    509			.data = &req,
    510			.size = sizeof(req),
    511		},
    512		.rx = {
    513			.data = &resp,
    514			.size = sizeof(resp),
    515		},
    516	};
    517	int err;
    518
    519	err = tegra_bpmp_transfer(bpmp, &msg);
    520	if (err < 0)
    521		return err;
    522	else if (msg.rx.ret < 0)
    523		return -EINVAL;
    524
    525	*nbytes = (size_t)resp.fop.nbytes;
    526
    527	return 0;
    528}
    529
    530static int mrq_debugfs_write(struct tegra_bpmp *bpmp,
    531			     dma_addr_t name, size_t sz_name,
    532			     dma_addr_t data, size_t sz_data)
    533{
    534	const struct mrq_debugfs_request req = {
    535		.cmd = cpu_to_le32(CMD_DEBUGFS_WRITE),
    536		.fop = {
    537			.fnameaddr = cpu_to_le32((uint32_t)name),
    538			.fnamelen = cpu_to_le32((uint32_t)sz_name),
    539			.dataaddr = cpu_to_le32((uint32_t)data),
    540			.datalen = cpu_to_le32((uint32_t)sz_data),
    541		},
    542	};
    543	struct tegra_bpmp_message msg = {
    544		.mrq = MRQ_DEBUGFS,
    545		.tx = {
    546			.data = &req,
    547			.size = sizeof(req),
    548		},
    549	};
    550
    551	return tegra_bpmp_transfer(bpmp, &msg);
    552}
    553
    554static int mrq_debugfs_dumpdir(struct tegra_bpmp *bpmp, dma_addr_t addr,
    555			       size_t size, size_t *nbytes)
    556{
    557	const struct mrq_debugfs_request req = {
    558		.cmd = cpu_to_le32(CMD_DEBUGFS_DUMPDIR),
    559		.dumpdir = {
    560			.dataaddr = cpu_to_le32((uint32_t)addr),
    561			.datalen = cpu_to_le32((uint32_t)size),
    562		},
    563	};
    564	struct mrq_debugfs_response resp;
    565	struct tegra_bpmp_message msg = {
    566		.mrq = MRQ_DEBUGFS,
    567		.tx = {
    568			.data = &req,
    569			.size = sizeof(req),
    570		},
    571		.rx = {
    572			.data = &resp,
    573			.size = sizeof(resp),
    574		},
    575	};
    576	int err;
    577
    578	err = tegra_bpmp_transfer(bpmp, &msg);
    579	if (err < 0)
    580		return err;
    581	else if (msg.rx.ret < 0)
    582		return -EINVAL;
    583
    584	*nbytes = (size_t)resp.dumpdir.nbytes;
    585
    586	return 0;
    587}
    588
    589static int debugfs_show(struct seq_file *m, void *p)
    590{
    591	struct file *file = m->private;
    592	struct inode *inode = file_inode(file);
    593	struct tegra_bpmp *bpmp = inode->i_private;
    594	const size_t datasize = m->size;
    595	const size_t namesize = SZ_256;
    596	void *datavirt, *namevirt;
    597	dma_addr_t dataphys, namephys;
    598	char buf[256];
    599	const char *filename;
    600	size_t len, nbytes;
    601	int err;
    602
    603	filename = get_filename(bpmp, file, buf, sizeof(buf));
    604	if (!filename)
    605		return -ENOENT;
    606
    607	namevirt = dma_alloc_coherent(bpmp->dev, namesize, &namephys,
    608				      GFP_KERNEL | GFP_DMA32);
    609	if (!namevirt)
    610		return -ENOMEM;
    611
    612	datavirt = dma_alloc_coherent(bpmp->dev, datasize, &dataphys,
    613				      GFP_KERNEL | GFP_DMA32);
    614	if (!datavirt) {
    615		err = -ENOMEM;
    616		goto free_namebuf;
    617	}
    618
    619	len = strlen(filename);
    620	strncpy(namevirt, filename, namesize);
    621
    622	err = mrq_debugfs_read(bpmp, namephys, len, dataphys, datasize,
    623			       &nbytes);
    624
    625	if (!err)
    626		seq_write(m, datavirt, nbytes);
    627
    628	dma_free_coherent(bpmp->dev, datasize, datavirt, dataphys);
    629free_namebuf:
    630	dma_free_coherent(bpmp->dev, namesize, namevirt, namephys);
    631
    632	return err;
    633}
    634
    635static int debugfs_open(struct inode *inode, struct file *file)
    636{
    637	return single_open_size(file, debugfs_show, file, SZ_128K);
    638}
    639
    640static ssize_t debugfs_store(struct file *file, const char __user *buf,
    641		size_t count, loff_t *f_pos)
    642{
    643	struct inode *inode = file_inode(file);
    644	struct tegra_bpmp *bpmp = inode->i_private;
    645	const size_t datasize = count;
    646	const size_t namesize = SZ_256;
    647	void *datavirt, *namevirt;
    648	dma_addr_t dataphys, namephys;
    649	char fnamebuf[256];
    650	const char *filename;
    651	size_t len;
    652	int err;
    653
    654	filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
    655	if (!filename)
    656		return -ENOENT;
    657
    658	namevirt = dma_alloc_coherent(bpmp->dev, namesize, &namephys,
    659				      GFP_KERNEL | GFP_DMA32);
    660	if (!namevirt)
    661		return -ENOMEM;
    662
    663	datavirt = dma_alloc_coherent(bpmp->dev, datasize, &dataphys,
    664				      GFP_KERNEL | GFP_DMA32);
    665	if (!datavirt) {
    666		err = -ENOMEM;
    667		goto free_namebuf;
    668	}
    669
    670	len = strlen(filename);
    671	strncpy(namevirt, filename, namesize);
    672
    673	if (copy_from_user(datavirt, buf, count)) {
    674		err = -EFAULT;
    675		goto free_databuf;
    676	}
    677
    678	err = mrq_debugfs_write(bpmp, namephys, len, dataphys,
    679				count);
    680
    681free_databuf:
    682	dma_free_coherent(bpmp->dev, datasize, datavirt, dataphys);
    683free_namebuf:
    684	dma_free_coherent(bpmp->dev, namesize, namevirt, namephys);
    685
    686	return err ?: count;
    687}
    688
    689static const struct file_operations debugfs_fops = {
    690	.open		= debugfs_open,
    691	.read		= seq_read,
    692	.llseek		= seq_lseek,
    693	.write		= debugfs_store,
    694	.release	= single_release,
    695};
    696
    697static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf,
    698			     struct dentry *parent, uint32_t depth)
    699{
    700	int err;
    701	uint32_t d, t;
    702	const char *name;
    703	struct dentry *dentry;
    704
    705	while (!seqbuf_eof(seqbuf)) {
    706		err = seqbuf_read_u32(seqbuf, &d);
    707		if (err < 0)
    708			return err;
    709
    710		if (d < depth) {
    711			seqbuf_seek(seqbuf, -4);
    712			/* go up a level */
    713			return 0;
    714		} else if (d != depth) {
    715			/* malformed data received from BPMP */
    716			return -EIO;
    717		}
    718
    719		err = seqbuf_read_u32(seqbuf, &t);
    720		if (err < 0)
    721			return err;
    722		err = seqbuf_read_str(seqbuf, &name);
    723		if (err < 0)
    724			return err;
    725
    726		if (t & DEBUGFS_S_ISDIR) {
    727			dentry = debugfs_create_dir(name, parent);
    728			if (!dentry)
    729				return -ENOMEM;
    730			err = bpmp_populate_dir(bpmp, seqbuf, dentry, depth+1);
    731			if (err < 0)
    732				return err;
    733		} else {
    734			umode_t mode;
    735
    736			mode = t & DEBUGFS_S_IRUSR ? S_IRUSR : 0;
    737			mode |= t & DEBUGFS_S_IWUSR ? S_IWUSR : 0;
    738			dentry = debugfs_create_file(name, mode,
    739						     parent, bpmp,
    740						     &debugfs_fops);
    741			if (!dentry)
    742				return -ENOMEM;
    743		}
    744	}
    745
    746	return 0;
    747}
    748
    749static int bpmp_populate_debugfs_shmem(struct tegra_bpmp *bpmp)
    750{
    751	struct seqbuf seqbuf;
    752	const size_t sz = SZ_512K;
    753	dma_addr_t phys;
    754	size_t nbytes;
    755	void *virt;
    756	int err;
    757
    758	virt = dma_alloc_coherent(bpmp->dev, sz, &phys,
    759				  GFP_KERNEL | GFP_DMA32);
    760	if (!virt)
    761		return -ENOMEM;
    762
    763	err = mrq_debugfs_dumpdir(bpmp, phys, sz, &nbytes);
    764	if (err < 0) {
    765		goto free;
    766	} else if (nbytes > sz) {
    767		err = -EINVAL;
    768		goto free;
    769	}
    770
    771	seqbuf_init(&seqbuf, virt, nbytes);
    772	err = bpmp_populate_dir(bpmp, &seqbuf, bpmp->debugfs_mirror, 0);
    773free:
    774	dma_free_coherent(bpmp->dev, sz, virt, phys);
    775
    776	return err;
    777}
    778
    779int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp)
    780{
    781	struct dentry *root;
    782	bool inband;
    783	int err;
    784
    785	inband = tegra_bpmp_mrq_is_supported(bpmp, MRQ_DEBUG);
    786
    787	if (!inband && !tegra_bpmp_mrq_is_supported(bpmp, MRQ_DEBUGFS))
    788		return 0;
    789
    790	root = debugfs_create_dir("bpmp", NULL);
    791	if (!root)
    792		return -ENOMEM;
    793
    794	bpmp->debugfs_mirror = debugfs_create_dir("debug", root);
    795	if (!bpmp->debugfs_mirror) {
    796		err = -ENOMEM;
    797		goto out;
    798	}
    799
    800	if (inband)
    801		err = bpmp_populate_debugfs_inband(bpmp, bpmp->debugfs_mirror,
    802						   "/");
    803	else
    804		err = bpmp_populate_debugfs_shmem(bpmp);
    805
    806out:
    807	if (err < 0)
    808		debugfs_remove_recursive(root);
    809
    810	return err;
    811}