cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xensyms.c (3203B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/init.h>
      3#include <linux/seq_file.h>
      4#include <linux/fs.h>
      5#include <linux/mm.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>
     11#include "xenfs.h"
     12
     13
     14#define XEN_KSYM_NAME_LEN 127 /* Hypervisor may have different name length */
     15
     16struct xensyms {
     17	struct xen_platform_op op;
     18	char *name;
     19	uint32_t namelen;
     20};
     21
     22/* Grab next output page from the hypervisor */
     23static int xensyms_next_sym(struct xensyms *xs)
     24{
     25	int ret;
     26	struct xenpf_symdata *symdata = &xs->op.u.symdata;
     27	uint64_t symnum;
     28
     29	memset(xs->name, 0, xs->namelen);
     30	symdata->namelen = xs->namelen;
     31
     32	symnum = symdata->symnum;
     33
     34	ret = HYPERVISOR_platform_op(&xs->op);
     35	if (ret < 0)
     36		return ret;
     37
     38	/*
     39	 * If hypervisor's symbol didn't fit into the buffer then allocate
     40	 * a larger buffer and try again.
     41	 */
     42	if (unlikely(symdata->namelen > xs->namelen)) {
     43		kfree(xs->name);
     44
     45		xs->namelen = symdata->namelen;
     46		xs->name = kzalloc(xs->namelen, GFP_KERNEL);
     47		if (!xs->name)
     48			return -ENOMEM;
     49
     50		set_xen_guest_handle(symdata->name, xs->name);
     51		symdata->symnum--; /* Rewind */
     52
     53		ret = HYPERVISOR_platform_op(&xs->op);
     54		if (ret < 0)
     55			return ret;
     56	}
     57
     58	if (symdata->symnum == symnum)
     59		/* End of symbols */
     60		return 1;
     61
     62	return 0;
     63}
     64
     65static void *xensyms_start(struct seq_file *m, loff_t *pos)
     66{
     67	struct xensyms *xs = (struct xensyms *)m->private;
     68
     69	xs->op.u.symdata.symnum = *pos;
     70
     71	if (xensyms_next_sym(xs))
     72		return NULL;
     73
     74	return m->private;
     75}
     76
     77static void *xensyms_next(struct seq_file *m, void *p, loff_t *pos)
     78{
     79	struct xensyms *xs = (struct xensyms *)m->private;
     80
     81	xs->op.u.symdata.symnum = ++(*pos);
     82
     83	if (xensyms_next_sym(xs))
     84		return NULL;
     85
     86	return p;
     87}
     88
     89static int xensyms_show(struct seq_file *m, void *p)
     90{
     91	struct xensyms *xs = (struct xensyms *)m->private;
     92	struct xenpf_symdata *symdata = &xs->op.u.symdata;
     93
     94	seq_printf(m, "%016llx %c %s\n", symdata->address,
     95		   symdata->type, xs->name);
     96
     97	return 0;
     98}
     99
    100static void xensyms_stop(struct seq_file *m, void *p)
    101{
    102}
    103
    104static const struct seq_operations xensyms_seq_ops = {
    105	.start = xensyms_start,
    106	.next = xensyms_next,
    107	.show = xensyms_show,
    108	.stop = xensyms_stop,
    109};
    110
    111static int xensyms_open(struct inode *inode, struct file *file)
    112{
    113	struct seq_file *m;
    114	struct xensyms *xs;
    115	int ret;
    116
    117	ret = seq_open_private(file, &xensyms_seq_ops,
    118			       sizeof(struct xensyms));
    119	if (ret)
    120		return ret;
    121
    122	m = file->private_data;
    123	xs = (struct xensyms *)m->private;
    124
    125	xs->namelen = XEN_KSYM_NAME_LEN + 1;
    126	xs->name = kzalloc(xs->namelen, GFP_KERNEL);
    127	if (!xs->name) {
    128		seq_release_private(inode, file);
    129		return -ENOMEM;
    130	}
    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;
    134
    135	return 0;
    136}
    137
    138static int xensyms_release(struct inode *inode, struct file *file)
    139{
    140	struct seq_file *m = file->private_data;
    141	struct xensyms *xs = (struct xensyms *)m->private;
    142
    143	kfree(xs->name);
    144	return seq_release_private(inode, file);
    145}
    146
    147const struct file_operations xensyms_ops = {
    148	.open = xensyms_open,
    149	.read = seq_read,
    150	.llseek = seq_lseek,
    151	.release = xensyms_release
    152};