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