Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/init.h>
0003 #include <linux/seq_file.h>
0004 #include <linux/fs.h>
0005 #include <linux/mm.h>
0006 #include <linux/proc_fs.h>
0007 #include <linux/slab.h>
0008 #include <xen/interface/platform.h>
0009 #include <asm/xen/hypercall.h>
0010 #include <xen/xen-ops.h>
0011 #include "xenfs.h"
0012 
0013 
0014 #define XEN_KSYM_NAME_LEN 127 /* Hypervisor may have different name length */
0015 
0016 struct xensyms {
0017     struct xen_platform_op op;
0018     char *name;
0019     uint32_t namelen;
0020 };
0021 
0022 /* Grab next output page from the hypervisor */
0023 static int xensyms_next_sym(struct xensyms *xs)
0024 {
0025     int ret;
0026     struct xenpf_symdata *symdata = &xs->op.u.symdata;
0027     uint64_t symnum;
0028 
0029     memset(xs->name, 0, xs->namelen);
0030     symdata->namelen = xs->namelen;
0031 
0032     symnum = symdata->symnum;
0033 
0034     ret = HYPERVISOR_platform_op(&xs->op);
0035     if (ret < 0)
0036         return ret;
0037 
0038     /*
0039      * If hypervisor's symbol didn't fit into the buffer then allocate
0040      * a larger buffer and try again.
0041      */
0042     if (unlikely(symdata->namelen > xs->namelen)) {
0043         kfree(xs->name);
0044 
0045         xs->namelen = symdata->namelen;
0046         xs->name = kzalloc(xs->namelen, GFP_KERNEL);
0047         if (!xs->name)
0048             return -ENOMEM;
0049 
0050         set_xen_guest_handle(symdata->name, xs->name);
0051         symdata->symnum--; /* Rewind */
0052 
0053         ret = HYPERVISOR_platform_op(&xs->op);
0054         if (ret < 0)
0055             return ret;
0056     }
0057 
0058     if (symdata->symnum == symnum)
0059         /* End of symbols */
0060         return 1;
0061 
0062     return 0;
0063 }
0064 
0065 static void *xensyms_start(struct seq_file *m, loff_t *pos)
0066 {
0067     struct xensyms *xs = (struct xensyms *)m->private;
0068 
0069     xs->op.u.symdata.symnum = *pos;
0070 
0071     if (xensyms_next_sym(xs))
0072         return NULL;
0073 
0074     return m->private;
0075 }
0076 
0077 static void *xensyms_next(struct seq_file *m, void *p, loff_t *pos)
0078 {
0079     struct xensyms *xs = (struct xensyms *)m->private;
0080 
0081     xs->op.u.symdata.symnum = ++(*pos);
0082 
0083     if (xensyms_next_sym(xs))
0084         return NULL;
0085 
0086     return p;
0087 }
0088 
0089 static int xensyms_show(struct seq_file *m, void *p)
0090 {
0091     struct xensyms *xs = (struct xensyms *)m->private;
0092     struct xenpf_symdata *symdata = &xs->op.u.symdata;
0093 
0094     seq_printf(m, "%016llx %c %s\n", symdata->address,
0095            symdata->type, xs->name);
0096 
0097     return 0;
0098 }
0099 
0100 static void xensyms_stop(struct seq_file *m, void *p)
0101 {
0102 }
0103 
0104 static const struct seq_operations xensyms_seq_ops = {
0105     .start = xensyms_start,
0106     .next = xensyms_next,
0107     .show = xensyms_show,
0108     .stop = xensyms_stop,
0109 };
0110 
0111 static int xensyms_open(struct inode *inode, struct file *file)
0112 {
0113     struct seq_file *m;
0114     struct xensyms *xs;
0115     int ret;
0116 
0117     ret = seq_open_private(file, &xensyms_seq_ops,
0118                    sizeof(struct xensyms));
0119     if (ret)
0120         return ret;
0121 
0122     m = file->private_data;
0123     xs = (struct xensyms *)m->private;
0124 
0125     xs->namelen = XEN_KSYM_NAME_LEN + 1;
0126     xs->name = kzalloc(xs->namelen, GFP_KERNEL);
0127     if (!xs->name) {
0128         seq_release_private(inode, file);
0129         return -ENOMEM;
0130     }
0131     set_xen_guest_handle(xs->op.u.symdata.name, xs->name);
0132     xs->op.cmd = XENPF_get_symbol;
0133     xs->op.u.symdata.namelen = xs->namelen;
0134 
0135     return 0;
0136 }
0137 
0138 static int xensyms_release(struct inode *inode, struct file *file)
0139 {
0140     struct seq_file *m = file->private_data;
0141     struct xensyms *xs = (struct xensyms *)m->private;
0142 
0143     kfree(xs->name);
0144     return seq_release_private(inode, file);
0145 }
0146 
0147 const struct file_operations xensyms_ops = {
0148     .open = xensyms_open,
0149     .read = seq_read,
0150     .llseek = seq_lseek,
0151     .release = xensyms_release
0152 };