1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/init.h>
3 #include <linux/seq_file.h>
6 #include <linux/proc_fs.h>
7 #include <linux/slab.h>
8 #include <xen/interface/platform.h>
9 #include <asm/xen/hypercall.h>
10 #include <xen/xen-ops.h>
14 #define XEN_KSYM_NAME_LEN 127 /* Hypervisor may have different name length */
17 struct xen_platform_op op
;
22 /* Grab next output page from the hypervisor */
23 static int xensyms_next_sym(struct xensyms
*xs
)
26 struct xenpf_symdata
*symdata
= &xs
->op
.u
.symdata
;
29 memset(xs
->name
, 0, xs
->namelen
);
30 symdata
->namelen
= xs
->namelen
;
32 symnum
= symdata
->symnum
;
34 ret
= HYPERVISOR_platform_op(&xs
->op
);
39 * If hypervisor's symbol didn't fit into the buffer then allocate
40 * a larger buffer and try again.
42 if (unlikely(symdata
->namelen
> xs
->namelen
)) {
45 xs
->namelen
= symdata
->namelen
;
46 xs
->name
= kzalloc(xs
->namelen
, GFP_KERNEL
);
50 set_xen_guest_handle(symdata
->name
, xs
->name
);
51 symdata
->symnum
--; /* Rewind */
53 ret
= HYPERVISOR_platform_op(&xs
->op
);
58 if (symdata
->symnum
== symnum
)
65 static void *xensyms_start(struct seq_file
*m
, loff_t
*pos
)
67 struct xensyms
*xs
= (struct xensyms
*)m
->private;
69 xs
->op
.u
.symdata
.symnum
= *pos
;
71 if (xensyms_next_sym(xs
))
77 static void *xensyms_next(struct seq_file
*m
, void *p
, loff_t
*pos
)
79 struct xensyms
*xs
= (struct xensyms
*)m
->private;
81 xs
->op
.u
.symdata
.symnum
= ++(*pos
);
83 if (xensyms_next_sym(xs
))
89 static int xensyms_show(struct seq_file
*m
, void *p
)
91 struct xensyms
*xs
= (struct xensyms
*)m
->private;
92 struct xenpf_symdata
*symdata
= &xs
->op
.u
.symdata
;
94 seq_printf(m
, "%016llx %c %s\n", symdata
->address
,
95 symdata
->type
, xs
->name
);
100 static void xensyms_stop(struct seq_file
*m
, void *p
)
104 static const struct seq_operations xensyms_seq_ops
= {
105 .start
= xensyms_start
,
106 .next
= xensyms_next
,
107 .show
= xensyms_show
,
108 .stop
= xensyms_stop
,
111 static int xensyms_open(struct inode
*inode
, struct file
*file
)
117 ret
= seq_open_private(file
, &xensyms_seq_ops
,
118 sizeof(struct xensyms
));
122 m
= file
->private_data
;
123 xs
= (struct xensyms
*)m
->private;
125 xs
->namelen
= XEN_KSYM_NAME_LEN
+ 1;
126 xs
->name
= kzalloc(xs
->namelen
, GFP_KERNEL
);
128 seq_release_private(inode
, file
);
131 set_xen_guest_handle(xs
->op
.u
.symdata
.name
, xs
->name
);
132 xs
->op
.cmd
= XENPF_get_symbol
;
133 xs
->op
.u
.symdata
.namelen
= xs
->namelen
;
138 static int xensyms_release(struct inode
*inode
, struct file
*file
)
140 struct seq_file
*m
= file
->private_data
;
141 struct xensyms
*xs
= (struct xensyms
*)m
->private;
144 return seq_release_private(inode
, file
);
147 const struct file_operations xensyms_ops
= {
148 .open
= xensyms_open
,
151 .release
= xensyms_release