1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2016-2018, Matthew Macy <mmacy@freebsd.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/queue.h>
32#include <sys/blist.h>
33#include <sys/conf.h>
34#include <sys/exec.h>
35#include <sys/filedesc.h>
36#include <sys/kernel.h>
37#include <sys/linker.h>
38#include <sys/malloc.h>
39#include <sys/mount.h>
40#include <sys/mutex.h>
41#include <sys/proc.h>
42#include <sys/resourcevar.h>
43#include <sys/sbuf.h>
44#include <sys/smp.h>
45#include <sys/socket.h>
46#include <sys/vnode.h>
47#include <sys/bus.h>
48#include <sys/pciio.h>
49
50#include <dev/pci/pcivar.h>
51#include <dev/pci/pcireg.h>
52
53#include <net/if.h>
54
55#include <vm/vm.h>
56#include <vm/pmap.h>
57#include <vm/vm_map.h>
58#include <vm/vm_param.h>
59#include <vm/vm_object.h>
60#include <vm/swap_pager.h>
61
62#include <machine/bus.h>
63
64#include <compat/linux/linux_ioctl.h>
65#include <compat/linux/linux_mib.h>
66#include <compat/linux/linux_util.h>
67#include <fs/pseudofs/pseudofs.h>
68
69#include <asm/atomic.h>
70#include <linux/compat.h>
71#include <linux/debugfs.h>
72#include <linux/fs.h>
73
74MALLOC_DEFINE(M_DFSINT, "debugfsint", "Linux debugfs internal");
75
76static struct pfs_node *debugfs_root;
77
78#define DM_SYMLINK 0x1
79#define DM_DIR 0x2
80#define DM_FILE 0x3
81
82struct dentry_meta {
83	struct dentry dm_dnode;
84	const struct file_operations *dm_fops;
85	void *dm_data;
86	umode_t dm_mode;
87	int dm_type;
88};
89
90static int
91debugfs_attr(PFS_ATTR_ARGS)
92{
93	struct dentry_meta *dm;
94
95	dm = pn->pn_data;
96
97	vap->va_mode = dm->dm_mode;
98	return (0);
99}
100
101static int
102debugfs_destroy(PFS_DESTROY_ARGS)
103{
104	struct dentry_meta *dm;
105
106	dm = pn->pn_data;
107	if (dm->dm_type == DM_SYMLINK)
108		free(dm->dm_data, M_DFSINT);
109
110	free(dm, M_DFSINT);
111	return (0);
112}
113
114static int
115debugfs_fill(PFS_FILL_ARGS)
116{
117	struct dentry_meta *d;
118	struct linux_file lf = {};
119	struct vnode vn;
120	char *buf;
121	int rc;
122	off_t off = 0;
123
124	if ((rc = linux_set_current_flags(curthread, M_NOWAIT)))
125		return (rc);
126
127	d = pn->pn_data;
128	vn.v_data = d->dm_data;
129
130	rc = d->dm_fops->open(&vn, &lf);
131	if (rc < 0) {
132#ifdef INVARIANTS
133		printf("%s:%d open failed with %d\n", __FUNCTION__, __LINE__, rc);
134#endif
135		return (-rc);
136	}
137
138	rc = -ENODEV;
139	switch (uio->uio_rw) {
140	case UIO_READ:
141		if (d->dm_fops->read != NULL) {
142			rc = -ENOMEM;
143			buf = malloc(sb->s_size, M_DFSINT, M_ZERO | M_NOWAIT);
144			if (buf != NULL) {
145				rc = d->dm_fops->read(&lf, buf, sb->s_size,
146				    &off);
147				if (rc > 0)
148					sbuf_bcpy(sb, buf, strlen(buf));
149
150				free(buf, M_DFSINT);
151			}
152		}
153		break;
154	case UIO_WRITE:
155		if (d->dm_fops->write != NULL) {
156			sbuf_finish(sb);
157			rc = d->dm_fops->write(&lf, sbuf_data(sb), sbuf_len(sb),
158			    &off);
159		}
160		break;
161	}
162
163	if (d->dm_fops->release)
164		d->dm_fops->release(&vn, &lf);
165	else
166		single_release(&vn, &lf);
167
168	if (rc < 0) {
169#ifdef INVARIANTS
170		printf("%s:%d read/write failed with %d\n", __FUNCTION__, __LINE__, rc);
171#endif
172		return (-rc);
173	}
174	return (0);
175}
176
177static int
178debugfs_fill_data(PFS_FILL_ARGS)
179{
180	struct dentry_meta *dm;
181
182	dm = pn->pn_data;
183	sbuf_printf(sb, "%s", (char *)dm->dm_data);
184	return (0);
185}
186
187struct dentry *
188debugfs_create_file(const char *name, umode_t mode,
189    struct dentry *parent, void *data,
190    const struct file_operations *fops)
191{
192	struct dentry_meta *dm;
193	struct dentry *dnode;
194	struct pfs_node *pnode;
195	int flags;
196
197	dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO);
198	if (dm == NULL)
199		return (NULL);
200	dnode = &dm->dm_dnode;
201	dm->dm_fops = fops;
202	dm->dm_data = data;
203	dm->dm_mode = mode;
204	dm->dm_type = DM_FILE;
205	if (parent != NULL)
206		pnode = parent->d_pfs_node;
207	else
208		pnode = debugfs_root;
209
210	flags = fops->write ? PFS_RDWR : PFS_RD;
211	dnode->d_pfs_node = pfs_create_file(pnode, name, debugfs_fill,
212	    debugfs_attr, NULL, debugfs_destroy, flags | PFS_NOWAIT);
213	if (dnode->d_pfs_node == NULL) {
214		free(dm, M_DFSINT);
215		return (NULL);
216	}
217	dnode->d_pfs_node->pn_data = dm;
218
219	return (dnode);
220}
221
222struct dentry *
223debugfs_create_file_size(const char *name, umode_t mode,
224    struct dentry *parent, void *data,
225    const struct file_operations *fops,
226    loff_t file_size __unused)
227{
228
229	return debugfs_create_file(name, mode, parent, data, fops);
230}
231
232/*
233 * NOTE: Files created with the _unsafe moniker will not be protected from
234 * debugfs core file removals. It is the responsibility of @fops to protect
235 * its file using debugfs_file_get() and debugfs_file_put().
236 *
237 * FreeBSD's LinuxKPI lindebugfs does not perform file removals at the time
238 * of writing. Therefore there is no difference between functions with _unsafe
239 * and functions without _unsafe when using lindebugfs. Functions with _unsafe
240 * exist only for Linux compatibility.
241 */
242struct dentry *
243debugfs_create_file_unsafe(const char *name, umode_t mode,
244    struct dentry *parent, void *data,
245    const struct file_operations *fops)
246{
247
248	return (debugfs_create_file(name, mode, parent, data, fops));
249}
250
251struct dentry *
252debugfs_create_mode_unsafe(const char *name, umode_t mode,
253    struct dentry *parent, void *data,
254    const struct file_operations *fops,
255    const struct file_operations *fops_ro,
256    const struct file_operations *fops_wo)
257{
258	umode_t read = mode & S_IRUGO;
259	umode_t write = mode & S_IWUGO;
260
261	if (read && !write)
262		return (debugfs_create_file_unsafe(name, mode, parent, data, fops_ro));
263
264	if (write && !read)
265		return (debugfs_create_file_unsafe(name, mode, parent, data, fops_wo));
266
267	return (debugfs_create_file_unsafe(name, mode, parent, data, fops));
268}
269
270struct dentry *
271debugfs_create_dir(const char *name, struct dentry *parent)
272{
273	struct dentry_meta *dm;
274	struct dentry *dnode;
275	struct pfs_node *pnode;
276
277	dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO);
278	if (dm == NULL)
279		return (NULL);
280	dnode = &dm->dm_dnode;
281	dm->dm_mode = 0700;
282	dm->dm_type = DM_DIR;
283	if (parent != NULL)
284		pnode = parent->d_pfs_node;
285	else
286		pnode = debugfs_root;
287
288	dnode->d_pfs_node = pfs_create_dir(pnode, name, debugfs_attr, NULL, debugfs_destroy, PFS_RD | PFS_NOWAIT);
289	if (dnode->d_pfs_node == NULL) {
290		free(dm, M_DFSINT);
291		return (NULL);
292	}
293	dnode->d_pfs_node->pn_data = dm;
294	return (dnode);
295}
296
297struct dentry *
298debugfs_create_symlink(const char *name, struct dentry *parent,
299    const char *dest)
300{
301	struct dentry_meta *dm;
302	struct dentry *dnode;
303	struct pfs_node *pnode;
304	void *data;
305
306	data = strdup_flags(dest, M_DFSINT, M_NOWAIT);
307	if (data == NULL)
308		return (NULL);
309	dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO);
310	if (dm == NULL)
311		goto fail1;
312	dnode = &dm->dm_dnode;
313	dm->dm_mode = 0700;
314	dm->dm_type = DM_SYMLINK;
315	dm->dm_data = data;
316	if (parent != NULL)
317		pnode = parent->d_pfs_node;
318	else
319		pnode = debugfs_root;
320
321	dnode->d_pfs_node = pfs_create_link(pnode, name, &debugfs_fill_data, NULL, NULL, NULL, PFS_NOWAIT);
322	if (dnode->d_pfs_node == NULL)
323		goto fail;
324	dnode->d_pfs_node->pn_data = dm;
325	return (dnode);
326 fail:
327	free(dm, M_DFSINT);
328 fail1:
329	free(data, M_DFSINT);
330	return (NULL);
331}
332
333void
334debugfs_remove(struct dentry *dnode)
335{
336	if (dnode == NULL)
337		return;
338
339	pfs_destroy(dnode->d_pfs_node);
340}
341
342void
343debugfs_remove_recursive(struct dentry *dnode)
344{
345	if (dnode == NULL)
346		return;
347
348	pfs_destroy(dnode->d_pfs_node);
349}
350
351static int
352debugfs_bool_get(void *data, uint64_t *ullval)
353{
354	bool *bval = data;
355
356	if (*bval)
357		*ullval = 1;
358	else
359		*ullval = 0;
360
361	return (0);
362}
363
364static int
365debugfs_bool_set(void *data, uint64_t ullval)
366{
367	bool *bval = data;
368
369	if (ullval)
370		*bval = 1;
371	else
372		*bval = 0;
373
374	return (0);
375}
376
377DEFINE_DEBUGFS_ATTRIBUTE(fops_bool, debugfs_bool_get, debugfs_bool_set, "%llu\n");
378DEFINE_DEBUGFS_ATTRIBUTE(fops_bool_ro, debugfs_bool_get, NULL, "%llu\n");
379DEFINE_DEBUGFS_ATTRIBUTE(fops_bool_wo, NULL, debugfs_bool_set, "%llu\n");
380
381void
382debugfs_create_bool(const char *name, umode_t mode, struct dentry *parent, bool *value)
383{
384
385	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_bool,
386	    &fops_bool_ro, &fops_bool_wo);
387}
388
389
390static int
391debugfs_u8_get(void *data, uint64_t *value)
392{
393	uint8_t *u8data = data;
394	*value = *u8data;
395	return (0);
396}
397
398static int
399debugfs_u8_set(void *data, uint64_t value)
400{
401	uint8_t *u8data = data;
402	*u8data = (uint8_t)value;
403	return (0);
404}
405
406DEFINE_DEBUGFS_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%u\n");
407DEFINE_DEBUGFS_ATTRIBUTE(fops_u8_ro, debugfs_u8_get, NULL, "%u\n");
408DEFINE_DEBUGFS_ATTRIBUTE(fops_u8_wo, NULL, debugfs_u8_set, "%u\n");
409
410void
411debugfs_create_u8(const char *name, umode_t mode, struct dentry *parent, uint8_t *value)
412{
413
414	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u8,
415	    &fops_u8_ro, &fops_u8_wo);
416}
417
418DEFINE_DEBUGFS_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%016llx\n");
419DEFINE_DEBUGFS_ATTRIBUTE(fops_x8_ro, debugfs_u8_get, NULL, "0x%016llx\n");
420DEFINE_DEBUGFS_ATTRIBUTE(fops_x8_wo, NULL, debugfs_u8_set, "0x%016llx\n");
421
422void
423debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent, uint8_t *value)
424{
425
426	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x8,
427	    &fops_x8_ro, &fops_x8_wo);
428}
429
430
431static int
432debugfs_u16_get(void *data, uint64_t *value)
433{
434	uint16_t *u16data = data;
435	*value = *u16data;
436	return (0);
437}
438
439static int
440debugfs_u16_set(void *data, uint64_t value)
441{
442	uint16_t *u16data = data;
443	*u16data = (uint16_t)value;
444	return (0);
445}
446
447DEFINE_DEBUGFS_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%u\n");
448DEFINE_DEBUGFS_ATTRIBUTE(fops_u16_ro, debugfs_u16_get, NULL, "%u\n");
449DEFINE_DEBUGFS_ATTRIBUTE(fops_u16_wo, NULL, debugfs_u16_set, "%u\n");
450
451void
452debugfs_create_u16(const char *name, umode_t mode, struct dentry *parent, uint16_t *value)
453{
454
455	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u16,
456	    &fops_u16_ro, &fops_u16_wo);
457}
458
459DEFINE_DEBUGFS_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%016llx\n");
460DEFINE_DEBUGFS_ATTRIBUTE(fops_x16_ro, debugfs_u16_get, NULL, "0x%016llx\n");
461DEFINE_DEBUGFS_ATTRIBUTE(fops_x16_wo, NULL, debugfs_u16_set, "0x%016llx\n");
462
463void
464debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, uint16_t *value)
465{
466
467	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x16,
468	    &fops_x16_ro, &fops_x16_wo);
469}
470
471
472static int
473debugfs_u32_get(void *data, uint64_t *value)
474{
475	uint32_t *u32data = data;
476	*value = *u32data;
477	return (0);
478}
479
480static int
481debugfs_u32_set(void *data, uint64_t value)
482{
483	uint32_t *u32data = data;
484	*u32data = (uint32_t)value;
485	return (0);
486}
487
488DEFINE_DEBUGFS_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%u\n");
489DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_ro, debugfs_u32_get, NULL, "%u\n");
490DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%u\n");
491
492void
493debugfs_create_u32(const char *name, umode_t mode, struct dentry *parent, uint32_t *value)
494{
495
496	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u32,
497	    &fops_u32_ro, &fops_u32_wo);
498}
499
500DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%016llx\n");
501DEFINE_DEBUGFS_ATTRIBUTE(fops_x32_ro, debugfs_u32_get, NULL, "0x%016llx\n");
502DEFINE_DEBUGFS_ATTRIBUTE(fops_x32_wo, NULL, debugfs_u32_set, "0x%016llx\n");
503
504void
505debugfs_create_x32(const char *name, umode_t mode, struct dentry *parent, uint32_t *value)
506{
507
508	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x32,
509	    &fops_x32_ro, &fops_x32_wo);
510}
511
512
513static int
514debugfs_u64_get(void *data, uint64_t *value)
515{
516	uint64_t *u64data = data;
517	*value = *u64data;
518	return (0);
519}
520
521static int
522debugfs_u64_set(void *data, uint64_t value)
523{
524	uint64_t *u64data = data;
525	*u64data = (uint64_t)value;
526	return (0);
527}
528
529DEFINE_DEBUGFS_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%u\n");
530DEFINE_DEBUGFS_ATTRIBUTE(fops_u64_ro, debugfs_u64_get, NULL, "%u\n");
531DEFINE_DEBUGFS_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%u\n");
532
533void
534debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent, uint64_t *value)
535{
536
537	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u64,
538	    &fops_u64_ro, &fops_u64_wo);
539}
540
541DEFINE_DEBUGFS_ATTRIBUTE(fops_x64, debugfs_u64_get, debugfs_u64_set, "0x%016llx\n");
542DEFINE_DEBUGFS_ATTRIBUTE(fops_x64_ro, debugfs_u64_get, NULL, "0x%016llx\n");
543DEFINE_DEBUGFS_ATTRIBUTE(fops_x64_wo, NULL, debugfs_u64_set, "0x%016llx\n");
544
545void
546debugfs_create_x64(const char *name, umode_t mode, struct dentry *parent, uint64_t *value)
547{
548
549	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x64,
550	    &fops_x64_ro, &fops_x64_wo);
551}
552
553
554static int
555debugfs_ulong_get(void *data, uint64_t *value)
556{
557	uint64_t *uldata = data;
558	*value = *uldata;
559	return (0);
560}
561
562static int
563debugfs_ulong_set(void *data, uint64_t value)
564{
565	uint64_t *uldata = data;
566	*uldata = value;
567	return (0);
568}
569
570DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong, debugfs_ulong_get, debugfs_ulong_set, "%llu\n");
571DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong_ro, debugfs_ulong_get, NULL, "%llu\n");
572DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong_wo, NULL, debugfs_ulong_set, "%llu\n");
573
574void
575debugfs_create_ulong(const char *name, umode_t mode, struct dentry *parent, unsigned long *value)
576{
577
578	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_ulong,
579	    &fops_ulong_ro, &fops_ulong_wo);
580}
581
582
583static int
584debugfs_atomic_t_get(void *data, uint64_t *value)
585{
586	atomic_t *atomic_data = data;
587	*value = atomic_read(atomic_data);
588	return (0);
589}
590
591static int
592debugfs_atomic_t_set(void *data, uint64_t value)
593{
594	atomic_t *atomic_data = data;
595	atomic_set(atomic_data, (int)value);
596	return (0);
597}
598
599DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, debugfs_atomic_t_set, "%d\n");
600DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, "%d\n");
601DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, "%d\n");
602
603void
604debugfs_create_atomic_t(const char *name, umode_t mode, struct dentry *parent, atomic_t *value)
605{
606
607	debugfs_create_mode_unsafe(name, mode, parent, value, &fops_atomic_t,
608	    &fops_atomic_t_ro, &fops_atomic_t_wo);
609}
610
611
612static ssize_t
613fops_blob_read(struct file *filp, char __user *ubuf, size_t read_size, loff_t *ppos)
614{
615	struct debugfs_blob_wrapper *blob;
616
617	blob = filp->private_data;
618	if (blob == NULL)
619		return (-EINVAL);
620	if (blob->size == 0 || blob->data == NULL)
621		return (-EINVAL);
622
623	return (simple_read_from_buffer(ubuf, read_size, ppos, blob->data, blob->size));
624}
625
626static int
627fops_blob_open(struct inode *inode, struct file *filp)
628{
629
630	return (simple_open(inode, filp));
631}
632
633static const struct file_operations __fops_blob_ro = {
634	.owner = THIS_MODULE,
635	.open = fops_blob_open,
636	.read = fops_blob_read,
637	.llseek = no_llseek
638};
639
640struct dentry *
641debugfs_create_blob(const char *name, umode_t mode, struct dentry *parent,
642    struct debugfs_blob_wrapper *value)
643{
644	/* Blobs are read-only. */
645	return (debugfs_create_file(name, mode & 0444, parent, value, &__fops_blob_ro));
646}
647
648
649static int
650lindebugfs_init(PFS_INIT_ARGS)
651{
652
653	debugfs_root = pi->pi_root;
654
655	(void)debugfs_create_symlink("kcov", NULL, "/dev/kcov");
656
657	return (0);
658}
659
660static int
661lindebugfs_uninit(PFS_INIT_ARGS)
662{
663
664	return (0);
665}
666
667PSEUDOFS(lindebugfs, 1, VFCF_JAIL);
668MODULE_DEPEND(lindebugfs, linuxkpi, 1, 1, 1);
669