1 #include <linux/init.h>
2 #include <linux/seq_file.h>
5 #include <linux/proc_fs.h>
6 #include <linux/slab.h>
7 #include <xen/interface/platform.h>
8 #include <asm/xen/hypercall.h>
9 #include <xen/xen-ops.h>
13 #define XEN_KSYM_NAME_LEN 127 /* Hypervisor may have different name length */
16 struct xen_platform_op op
;
21 /* Grab next output page from the hypervisor */
22 static int xensyms_next_sym(struct xensyms
*xs
)
25 struct xenpf_symdata
*symdata
= &xs
->op
.u
.symdata
;
28 memset(xs
->name
, 0, xs
->namelen
);
29 symdata
->namelen
= xs
->namelen
;
31 symnum
= symdata
->symnum
;
33 ret
= HYPERVISOR_platform_op(&xs
->op
);
38 * If hypervisor's symbol didn't fit into the buffer then allocate
39 * a larger buffer and try again.
41 if (unlikely(symdata
->namelen
> xs
->namelen
)) {
44 xs
->namelen
= symdata
->namelen
;
45 xs
->name
= kzalloc(xs
->namelen
, GFP_KERNEL
);
49 set_xen_guest_handle(symdata
->name
, xs
->name
);
50 symdata
->symnum
--; /* Rewind */
52 ret
= HYPERVISOR_platform_op(&xs
->op
);
57 if (symdata
->symnum
== symnum
)
64 static void *xensyms_start(struct seq_file
*m
, loff_t
*pos
)
66 struct xensyms
*xs
= (struct xensyms
*)m
->private;
68 xs
->op
.u
.symdata
.symnum
= *pos
;
70 if (xensyms_next_sym(xs
))
76 static void *xensyms_next(struct seq_file
*m
, void *p
, loff_t
*pos
)
78 struct xensyms
*xs
= (struct xensyms
*)m
->private;
80 xs
->op
.u
.symdata
.symnum
= ++(*pos
);
82 if (xensyms_next_sym(xs
))
88 static int xensyms_show(struct seq_file
*m
, void *p
)
90 struct xensyms
*xs
= (struct xensyms
*)m
->private;
91 struct xenpf_symdata
*symdata
= &xs
->op
.u
.symdata
;
93 seq_printf(m
, "%016llx %c %s\n", symdata
->address
,
94 symdata
->type
, xs
->name
);
99 static void xensyms_stop(struct seq_file
*m
, void *p
)
103 static const struct seq_operations xensyms_seq_ops
= {
104 .start
= xensyms_start
,
105 .next
= xensyms_next
,
106 .show
= xensyms_show
,
107 .stop
= xensyms_stop
,
110 static int xensyms_open(struct inode
*inode
, struct file
*file
)
116 ret
= seq_open_private(file
, &xensyms_seq_ops
,
117 sizeof(struct xensyms
));
121 m
= file
->private_data
;
122 xs
= (struct xensyms
*)m
->private;
124 xs
->namelen
= XEN_KSYM_NAME_LEN
+ 1;
125 xs
->name
= kzalloc(xs
->namelen
, GFP_KERNEL
);
127 seq_release_private(inode
, file
);
130 set_xen_guest_handle(xs
->op
.u
.symdata
.name
, xs
->name
);
131 xs
->op
.cmd
= XENPF_get_symbol
;
132 xs
->op
.u
.symdata
.namelen
= xs
->namelen
;
137 static int xensyms_release(struct inode
*inode
, struct file
*file
)
139 struct seq_file
*m
= file
->private_data
;
140 struct xensyms
*xs
= (struct xensyms
*)m
->private;
143 return seq_release_private(inode
, file
);
146 const struct file_operations xensyms_ops
= {
147 .open
= xensyms_open
,
150 .release
= xensyms_release