xref: /linux/drivers/vfio/debugfs.c (revision 68a052239fc4b351e961f698b824f7654a346091)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2023, HiSilicon Ltd.
4  */
5 
6 #include <linux/device.h>
7 #include <linux/debugfs.h>
8 #include <linux/seq_file.h>
9 #include <linux/vfio.h>
10 #include "vfio.h"
11 
12 static struct dentry *vfio_debugfs_root;
13 
14 static int vfio_device_state_read(struct seq_file *seq, void *data)
15 {
16 	struct device *vf_dev = seq->private;
17 	struct vfio_device *vdev = container_of(vf_dev,
18 						struct vfio_device, device);
19 	enum vfio_device_mig_state state;
20 	int ret;
21 
22 	BUILD_BUG_ON(VFIO_DEVICE_STATE_NR !=
23 		     VFIO_DEVICE_STATE_PRE_COPY_P2P + 1);
24 
25 	ret = vdev->mig_ops->migration_get_state(vdev, &state);
26 	if (ret)
27 		return -EINVAL;
28 
29 	switch (state) {
30 	case VFIO_DEVICE_STATE_ERROR:
31 		seq_puts(seq, "ERROR\n");
32 		break;
33 	case VFIO_DEVICE_STATE_STOP:
34 		seq_puts(seq, "STOP\n");
35 		break;
36 	case VFIO_DEVICE_STATE_RUNNING:
37 		seq_puts(seq, "RUNNING\n");
38 		break;
39 	case VFIO_DEVICE_STATE_STOP_COPY:
40 		seq_puts(seq, "STOP_COPY\n");
41 		break;
42 	case VFIO_DEVICE_STATE_RESUMING:
43 		seq_puts(seq, "RESUMING\n");
44 		break;
45 	case VFIO_DEVICE_STATE_RUNNING_P2P:
46 		seq_puts(seq, "RUNNING_P2P\n");
47 		break;
48 	case VFIO_DEVICE_STATE_PRE_COPY:
49 		seq_puts(seq, "PRE_COPY\n");
50 		break;
51 	case VFIO_DEVICE_STATE_PRE_COPY_P2P:
52 		seq_puts(seq, "PRE_COPY_P2P\n");
53 		break;
54 	default:
55 		seq_puts(seq, "Invalid\n");
56 	}
57 
58 	return 0;
59 }
60 
61 static int vfio_device_features_read(struct seq_file *seq, void *data)
62 {
63 	struct device *vf_dev = seq->private;
64 	struct vfio_device *vdev = container_of(vf_dev, struct vfio_device, device);
65 
66 	if (vdev->migration_flags & VFIO_MIGRATION_STOP_COPY)
67 		seq_puts(seq, "stop-copy\n");
68 	if (vdev->migration_flags & VFIO_MIGRATION_P2P)
69 		seq_puts(seq, "p2p\n");
70 	if (vdev->migration_flags & VFIO_MIGRATION_PRE_COPY)
71 		seq_puts(seq, "pre-copy\n");
72 	if (vdev->log_ops)
73 		seq_puts(seq, "dirty-tracking\n");
74 
75 	return 0;
76 }
77 
78 void vfio_device_debugfs_init(struct vfio_device *vdev)
79 {
80 	struct device *dev = &vdev->device;
81 
82 	vdev->debug_root = debugfs_create_dir(dev_name(vdev->dev),
83 					      vfio_debugfs_root);
84 
85 	if (vdev->mig_ops) {
86 		struct dentry *vfio_dev_migration = NULL;
87 
88 		vfio_dev_migration = debugfs_create_dir("migration",
89 							vdev->debug_root);
90 		debugfs_create_devm_seqfile(dev, "state", vfio_dev_migration,
91 					    vfio_device_state_read);
92 		debugfs_create_devm_seqfile(dev, "features", vfio_dev_migration,
93 					    vfio_device_features_read);
94 	}
95 }
96 
97 void vfio_device_debugfs_exit(struct vfio_device *vdev)
98 {
99 	debugfs_remove_recursive(vdev->debug_root);
100 }
101 
102 void vfio_debugfs_create_root(void)
103 {
104 	vfio_debugfs_root = debugfs_create_dir("vfio", NULL);
105 }
106 
107 void vfio_debugfs_remove_root(void)
108 {
109 	debugfs_remove_recursive(vfio_debugfs_root);
110 	vfio_debugfs_root = NULL;
111 }
112