xref: /freebsd/sys/compat/lindebugfs/lindebugfs.c (revision 3f6cab079cb20fc81f02f4acc7bd0032766c78d1)
1*3f6cab07SMatt Macy /*-
2*3f6cab07SMatt Macy  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*3f6cab07SMatt Macy  *
4*3f6cab07SMatt Macy  * Copyright (c) 2016-2018, Matthew Macy <mmacy@freebsd.org>
5*3f6cab07SMatt Macy  *
6*3f6cab07SMatt Macy  * Redistribution and use in source and binary forms, with or without
7*3f6cab07SMatt Macy  * modification, are permitted provided that the following conditions
8*3f6cab07SMatt Macy  * are met:
9*3f6cab07SMatt Macy  * 1. Redistributions of source code must retain the above copyright
10*3f6cab07SMatt Macy  *    notice, this list of conditions and the following disclaimer.
11*3f6cab07SMatt Macy  * 2. Redistributions in binary form must reproduce the above copyright
12*3f6cab07SMatt Macy  *    notice, this list of conditions and the following disclaimer in the
13*3f6cab07SMatt Macy  *    documentation and/or other materials provided with the distribution.
14*3f6cab07SMatt Macy  *
15*3f6cab07SMatt Macy  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*3f6cab07SMatt Macy  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*3f6cab07SMatt Macy  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*3f6cab07SMatt Macy  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*3f6cab07SMatt Macy  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*3f6cab07SMatt Macy  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*3f6cab07SMatt Macy  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*3f6cab07SMatt Macy  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*3f6cab07SMatt Macy  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*3f6cab07SMatt Macy  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*3f6cab07SMatt Macy  * SUCH DAMAGE.
26*3f6cab07SMatt Macy  *
27*3f6cab07SMatt Macy  */
28*3f6cab07SMatt Macy 
29*3f6cab07SMatt Macy #include <sys/cdefs.h>
30*3f6cab07SMatt Macy __FBSDID("$FreeBSD$");
31*3f6cab07SMatt Macy 
32*3f6cab07SMatt Macy #include <sys/param.h>
33*3f6cab07SMatt Macy #include <sys/systm.h>
34*3f6cab07SMatt Macy #include <sys/queue.h>
35*3f6cab07SMatt Macy #include <sys/blist.h>
36*3f6cab07SMatt Macy #include <sys/conf.h>
37*3f6cab07SMatt Macy #include <sys/exec.h>
38*3f6cab07SMatt Macy #include <sys/filedesc.h>
39*3f6cab07SMatt Macy #include <sys/kernel.h>
40*3f6cab07SMatt Macy #include <sys/linker.h>
41*3f6cab07SMatt Macy #include <sys/malloc.h>
42*3f6cab07SMatt Macy #include <sys/mount.h>
43*3f6cab07SMatt Macy #include <sys/mutex.h>
44*3f6cab07SMatt Macy #include <sys/proc.h>
45*3f6cab07SMatt Macy #include <sys/resourcevar.h>
46*3f6cab07SMatt Macy #include <sys/sbuf.h>
47*3f6cab07SMatt Macy #include <sys/smp.h>
48*3f6cab07SMatt Macy #include <sys/socket.h>
49*3f6cab07SMatt Macy #include <sys/vnode.h>
50*3f6cab07SMatt Macy #include <sys/bus.h>
51*3f6cab07SMatt Macy #include <sys/pciio.h>
52*3f6cab07SMatt Macy 
53*3f6cab07SMatt Macy #include <dev/pci/pcivar.h>
54*3f6cab07SMatt Macy #include <dev/pci/pcireg.h>
55*3f6cab07SMatt Macy 
56*3f6cab07SMatt Macy #include <net/if.h>
57*3f6cab07SMatt Macy 
58*3f6cab07SMatt Macy #include <vm/vm.h>
59*3f6cab07SMatt Macy #include <vm/pmap.h>
60*3f6cab07SMatt Macy #include <vm/vm_map.h>
61*3f6cab07SMatt Macy #include <vm/vm_param.h>
62*3f6cab07SMatt Macy #include <vm/vm_object.h>
63*3f6cab07SMatt Macy #include <vm/swap_pager.h>
64*3f6cab07SMatt Macy 
65*3f6cab07SMatt Macy #include <machine/bus.h>
66*3f6cab07SMatt Macy 
67*3f6cab07SMatt Macy #include <compat/linux/linux_ioctl.h>
68*3f6cab07SMatt Macy #include <compat/linux/linux_mib.h>
69*3f6cab07SMatt Macy #include <compat/linux/linux_util.h>
70*3f6cab07SMatt Macy #include <fs/pseudofs/pseudofs.h>
71*3f6cab07SMatt Macy 
72*3f6cab07SMatt Macy #include <linux/debugfs.h>
73*3f6cab07SMatt Macy #include <linux/seq_file.h>
74*3f6cab07SMatt Macy #include <linux/compat.h>
75*3f6cab07SMatt Macy 
76*3f6cab07SMatt Macy MALLOC_DEFINE(M_DFSINT, "debugfsint", "Linux debugfs internal");
77*3f6cab07SMatt Macy 
78*3f6cab07SMatt Macy static struct pfs_node *debugfs_root;
79*3f6cab07SMatt Macy 
80*3f6cab07SMatt Macy #define DM_SYMLINK 0x1
81*3f6cab07SMatt Macy #define DM_DIR 0x2
82*3f6cab07SMatt Macy #define DM_FILE 0x3
83*3f6cab07SMatt Macy 
84*3f6cab07SMatt Macy struct dentry_meta {
85*3f6cab07SMatt Macy 	struct dentry dm_dnode;
86*3f6cab07SMatt Macy 	const struct file_operations *dm_fops;
87*3f6cab07SMatt Macy 	void *dm_data;
88*3f6cab07SMatt Macy 	umode_t dm_mode;
89*3f6cab07SMatt Macy 	int dm_type;
90*3f6cab07SMatt Macy };
91*3f6cab07SMatt Macy 
92*3f6cab07SMatt Macy static int
93*3f6cab07SMatt Macy debugfs_attr(PFS_ATTR_ARGS)
94*3f6cab07SMatt Macy {
95*3f6cab07SMatt Macy 	struct dentry_meta *dm;
96*3f6cab07SMatt Macy 
97*3f6cab07SMatt Macy 	dm = pn->pn_data;
98*3f6cab07SMatt Macy 
99*3f6cab07SMatt Macy 	vap->va_mode = dm->dm_mode;
100*3f6cab07SMatt Macy 	return (0);
101*3f6cab07SMatt Macy }
102*3f6cab07SMatt Macy 
103*3f6cab07SMatt Macy static int
104*3f6cab07SMatt Macy debugfs_destroy(PFS_DESTROY_ARGS)
105*3f6cab07SMatt Macy {
106*3f6cab07SMatt Macy 	struct dentry_meta *dm;
107*3f6cab07SMatt Macy 
108*3f6cab07SMatt Macy 	dm = pn->pn_data;
109*3f6cab07SMatt Macy 	if (dm->dm_type == DM_SYMLINK)
110*3f6cab07SMatt Macy 		free(dm->dm_data, M_DFSINT);
111*3f6cab07SMatt Macy 
112*3f6cab07SMatt Macy 	free(dm, M_DFSINT);
113*3f6cab07SMatt Macy 	return (0);
114*3f6cab07SMatt Macy }
115*3f6cab07SMatt Macy 
116*3f6cab07SMatt Macy static int
117*3f6cab07SMatt Macy debugfs_fill(PFS_FILL_ARGS)
118*3f6cab07SMatt Macy {
119*3f6cab07SMatt Macy 	struct dentry_meta *d;
120*3f6cab07SMatt Macy 	struct linux_file lf;
121*3f6cab07SMatt Macy 	struct seq_file *sf;
122*3f6cab07SMatt Macy 	struct vnode vn;
123*3f6cab07SMatt Macy 	void *buf;
124*3f6cab07SMatt Macy 	int rc;
125*3f6cab07SMatt Macy 	size_t len;
126*3f6cab07SMatt Macy 	off_t off;
127*3f6cab07SMatt Macy 
128*3f6cab07SMatt Macy 	d = pn->pn_data;
129*3f6cab07SMatt Macy 
130*3f6cab07SMatt Macy 	if ((rc = linux_set_current_flags(curthread, M_NOWAIT)))
131*3f6cab07SMatt Macy 		return (rc);
132*3f6cab07SMatt Macy 	vn.v_data = d->dm_data;
133*3f6cab07SMatt Macy 	buf = uio->uio_iov[0].iov_base;
134*3f6cab07SMatt Macy 	len = min(uio->uio_iov[0].iov_len, uio->uio_resid);
135*3f6cab07SMatt Macy 	off = 0;
136*3f6cab07SMatt Macy 	lf.private_data = NULL;
137*3f6cab07SMatt Macy 	rc = d->dm_fops->open(&vn, &lf);
138*3f6cab07SMatt Macy 	if (rc < 0) {
139*3f6cab07SMatt Macy #ifdef INVARIANTS
140*3f6cab07SMatt Macy 		printf("%s:%d open failed with %d\n", __FUNCTION__, __LINE__, rc);
141*3f6cab07SMatt Macy #endif
142*3f6cab07SMatt Macy 		return (-rc);
143*3f6cab07SMatt Macy 	}
144*3f6cab07SMatt Macy 	sf = lf.private_data;
145*3f6cab07SMatt Macy 	sf->buf = sb;
146*3f6cab07SMatt Macy 	if (uio->uio_rw == UIO_READ)
147*3f6cab07SMatt Macy 		rc = d->dm_fops->read(&lf, NULL, len, &off);
148*3f6cab07SMatt Macy 	else
149*3f6cab07SMatt Macy 		rc = d->dm_fops->write(&lf, buf, len, &off);
150*3f6cab07SMatt Macy 	if (d->dm_fops->release)
151*3f6cab07SMatt Macy 		d->dm_fops->release(&vn, &lf);
152*3f6cab07SMatt Macy 	else
153*3f6cab07SMatt Macy 		single_release(&vn, &lf);
154*3f6cab07SMatt Macy 
155*3f6cab07SMatt Macy 	if (rc < 0) {
156*3f6cab07SMatt Macy #ifdef INVARIANTS
157*3f6cab07SMatt Macy 		printf("%s:%d read/write failed with %d\n", __FUNCTION__, __LINE__, rc);
158*3f6cab07SMatt Macy #endif
159*3f6cab07SMatt Macy 		return (-rc);
160*3f6cab07SMatt Macy 	}
161*3f6cab07SMatt Macy 	return (0);
162*3f6cab07SMatt Macy }
163*3f6cab07SMatt Macy 
164*3f6cab07SMatt Macy static int
165*3f6cab07SMatt Macy debugfs_fill_data(PFS_FILL_ARGS)
166*3f6cab07SMatt Macy {
167*3f6cab07SMatt Macy 	struct dentry_meta *dm;
168*3f6cab07SMatt Macy 
169*3f6cab07SMatt Macy 	dm = pn->pn_data;
170*3f6cab07SMatt Macy 	sbuf_printf(sb, "%s", (char *)dm->dm_data);
171*3f6cab07SMatt Macy 	return (0);
172*3f6cab07SMatt Macy }
173*3f6cab07SMatt Macy 
174*3f6cab07SMatt Macy struct dentry *
175*3f6cab07SMatt Macy debugfs_create_file(const char *name, umode_t mode,
176*3f6cab07SMatt Macy 		    struct dentry *parent, void *data,
177*3f6cab07SMatt Macy 		    const struct file_operations *fops)
178*3f6cab07SMatt Macy {
179*3f6cab07SMatt Macy 	struct dentry_meta *dm;
180*3f6cab07SMatt Macy 	struct dentry *dnode;
181*3f6cab07SMatt Macy 	struct pfs_node *pnode;
182*3f6cab07SMatt Macy 	int flags;
183*3f6cab07SMatt Macy 
184*3f6cab07SMatt Macy 	dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO);
185*3f6cab07SMatt Macy 	if (dm == NULL)
186*3f6cab07SMatt Macy 		return (NULL);
187*3f6cab07SMatt Macy 	dnode = &dm->dm_dnode;
188*3f6cab07SMatt Macy 	dm->dm_fops = fops;
189*3f6cab07SMatt Macy 	dm->dm_data = data;
190*3f6cab07SMatt Macy 	dm->dm_mode = mode;
191*3f6cab07SMatt Macy 	dm->dm_type = DM_FILE;
192*3f6cab07SMatt Macy 	if (parent != NULL)
193*3f6cab07SMatt Macy 		pnode = parent->d_pfs_node;
194*3f6cab07SMatt Macy 	else
195*3f6cab07SMatt Macy 		pnode = debugfs_root;
196*3f6cab07SMatt Macy 
197*3f6cab07SMatt Macy 	flags = fops->write ? PFS_RDWR : PFS_RD;
198*3f6cab07SMatt Macy 	dnode->d_pfs_node = pfs_create_file(pnode, name, debugfs_fill,
199*3f6cab07SMatt Macy 	    debugfs_attr, NULL, debugfs_destroy, flags | PFS_NOWAIT);
200*3f6cab07SMatt Macy 	if (dnode->d_pfs_node == NULL) {
201*3f6cab07SMatt Macy 		free(dm, M_DFSINT);
202*3f6cab07SMatt Macy 		return (NULL);
203*3f6cab07SMatt Macy 	}
204*3f6cab07SMatt Macy 	dnode->d_pfs_node->pn_data = dm;
205*3f6cab07SMatt Macy 
206*3f6cab07SMatt Macy 	return (dnode);
207*3f6cab07SMatt Macy }
208*3f6cab07SMatt Macy 
209*3f6cab07SMatt Macy struct dentry *
210*3f6cab07SMatt Macy debugfs_create_dir(const char *name, struct dentry *parent)
211*3f6cab07SMatt Macy {
212*3f6cab07SMatt Macy 	struct dentry_meta *dm;
213*3f6cab07SMatt Macy 	struct dentry *dnode;
214*3f6cab07SMatt Macy 	struct pfs_node *pnode;
215*3f6cab07SMatt Macy 
216*3f6cab07SMatt Macy 	dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO);
217*3f6cab07SMatt Macy 	if (dm == NULL)
218*3f6cab07SMatt Macy 		return (NULL);
219*3f6cab07SMatt Macy 	dnode = &dm->dm_dnode;
220*3f6cab07SMatt Macy 	dm->dm_mode = 0700;
221*3f6cab07SMatt Macy 	dm->dm_type = DM_DIR;
222*3f6cab07SMatt Macy 	if (parent != NULL)
223*3f6cab07SMatt Macy 		pnode = parent->d_pfs_node;
224*3f6cab07SMatt Macy 	else
225*3f6cab07SMatt Macy 		pnode = debugfs_root;
226*3f6cab07SMatt Macy 
227*3f6cab07SMatt Macy 	dnode->d_pfs_node = pfs_create_dir(pnode, name, debugfs_attr, NULL, debugfs_destroy, PFS_RD | PFS_NOWAIT);
228*3f6cab07SMatt Macy 	if (dnode->d_pfs_node == NULL) {
229*3f6cab07SMatt Macy 		free(dm, M_DFSINT);
230*3f6cab07SMatt Macy 		return (NULL);
231*3f6cab07SMatt Macy 	}
232*3f6cab07SMatt Macy 	dnode->d_pfs_node->pn_data = dm;
233*3f6cab07SMatt Macy 	return (dnode);
234*3f6cab07SMatt Macy }
235*3f6cab07SMatt Macy 
236*3f6cab07SMatt Macy struct dentry *
237*3f6cab07SMatt Macy debugfs_create_symlink(const char *name, struct dentry *parent,
238*3f6cab07SMatt Macy 	const char *dest)
239*3f6cab07SMatt Macy {
240*3f6cab07SMatt Macy 	struct dentry_meta *dm;
241*3f6cab07SMatt Macy 	struct dentry *dnode;
242*3f6cab07SMatt Macy 	struct pfs_node *pnode;
243*3f6cab07SMatt Macy 	void *data;
244*3f6cab07SMatt Macy 
245*3f6cab07SMatt Macy 	data = strdup_flags(dest, M_DFSINT, M_NOWAIT);
246*3f6cab07SMatt Macy 	if (data == NULL)
247*3f6cab07SMatt Macy 		return (NULL);
248*3f6cab07SMatt Macy 	dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO);
249*3f6cab07SMatt Macy 	if (dm == NULL)
250*3f6cab07SMatt Macy 		goto fail1;
251*3f6cab07SMatt Macy 	dnode = &dm->dm_dnode;
252*3f6cab07SMatt Macy 	dm->dm_mode = 0700;
253*3f6cab07SMatt Macy 	dm->dm_type = DM_SYMLINK;
254*3f6cab07SMatt Macy 	dm->dm_data = data;
255*3f6cab07SMatt Macy 	if (parent != NULL)
256*3f6cab07SMatt Macy 		pnode = parent->d_pfs_node;
257*3f6cab07SMatt Macy 	else
258*3f6cab07SMatt Macy 		pnode = debugfs_root;
259*3f6cab07SMatt Macy 
260*3f6cab07SMatt Macy 	dnode->d_pfs_node = pfs_create_link(pnode, name, &debugfs_fill_data, NULL, NULL, NULL, PFS_NOWAIT);
261*3f6cab07SMatt Macy 	if (dnode->d_pfs_node == NULL)
262*3f6cab07SMatt Macy 		goto fail;
263*3f6cab07SMatt Macy 	dnode->d_pfs_node->pn_data = dm;
264*3f6cab07SMatt Macy 	return (dnode);
265*3f6cab07SMatt Macy  fail:
266*3f6cab07SMatt Macy 	free(dm, M_DFSINT);
267*3f6cab07SMatt Macy  fail1:
268*3f6cab07SMatt Macy 	free(data, M_DFSINT);
269*3f6cab07SMatt Macy 	return (NULL);
270*3f6cab07SMatt Macy }
271*3f6cab07SMatt Macy 
272*3f6cab07SMatt Macy void
273*3f6cab07SMatt Macy debugfs_remove(struct dentry *dnode)
274*3f6cab07SMatt Macy {
275*3f6cab07SMatt Macy 	if (dnode == NULL)
276*3f6cab07SMatt Macy 		return;
277*3f6cab07SMatt Macy 
278*3f6cab07SMatt Macy 	pfs_destroy(dnode->d_pfs_node);
279*3f6cab07SMatt Macy }
280*3f6cab07SMatt Macy 
281*3f6cab07SMatt Macy void
282*3f6cab07SMatt Macy debugfs_remove_recursive(struct dentry *dnode)
283*3f6cab07SMatt Macy {
284*3f6cab07SMatt Macy 	if (dnode == NULL)
285*3f6cab07SMatt Macy 		return;
286*3f6cab07SMatt Macy 
287*3f6cab07SMatt Macy 	pfs_destroy(dnode->d_pfs_node);
288*3f6cab07SMatt Macy }
289*3f6cab07SMatt Macy 
290*3f6cab07SMatt Macy 
291*3f6cab07SMatt Macy static int
292*3f6cab07SMatt Macy debugfs_init(PFS_INIT_ARGS)
293*3f6cab07SMatt Macy {
294*3f6cab07SMatt Macy 
295*3f6cab07SMatt Macy 	debugfs_root = pi->pi_root;
296*3f6cab07SMatt Macy 	return (0);
297*3f6cab07SMatt Macy }
298*3f6cab07SMatt Macy 
299*3f6cab07SMatt Macy static int
300*3f6cab07SMatt Macy debugfs_uninit(PFS_INIT_ARGS)
301*3f6cab07SMatt Macy {
302*3f6cab07SMatt Macy 	return (0);
303*3f6cab07SMatt Macy }
304*3f6cab07SMatt Macy 
305*3f6cab07SMatt Macy #ifdef PR_ALLOW_MOUNT_LINSYSFS
306*3f6cab07SMatt Macy PSEUDOFS(debugfs, 1, PR_ALLOW_MOUNT_LINSYSFS);
307*3f6cab07SMatt Macy #else
308*3f6cab07SMatt Macy PSEUDOFS(debugfs, 1, VFCF_JAIL);
309*3f6cab07SMatt Macy #endif
310