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

bus.c (4698B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2021 ARM Ltd.
      4 */
      5
      6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      7
      8#include <linux/arm_ffa.h>
      9#include <linux/device.h>
     10#include <linux/fs.h>
     11#include <linux/kernel.h>
     12#include <linux/module.h>
     13#include <linux/slab.h>
     14#include <linux/types.h>
     15
     16#include "common.h"
     17
     18static int ffa_device_match(struct device *dev, struct device_driver *drv)
     19{
     20	const struct ffa_device_id *id_table;
     21	struct ffa_device *ffa_dev;
     22
     23	id_table = to_ffa_driver(drv)->id_table;
     24	ffa_dev = to_ffa_dev(dev);
     25
     26	while (!uuid_is_null(&id_table->uuid)) {
     27		/*
     28		 * FF-A v1.0 doesn't provide discovery of UUIDs, just the
     29		 * partition IDs, so fetch the partitions IDs for this
     30		 * id_table UUID and assign the UUID to the device if the
     31		 * partition ID matches
     32		 */
     33		if (uuid_is_null(&ffa_dev->uuid))
     34			ffa_device_match_uuid(ffa_dev, &id_table->uuid);
     35
     36		if (uuid_equal(&ffa_dev->uuid, &id_table->uuid))
     37			return 1;
     38		id_table++;
     39	}
     40
     41	return 0;
     42}
     43
     44static int ffa_device_probe(struct device *dev)
     45{
     46	struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
     47	struct ffa_device *ffa_dev = to_ffa_dev(dev);
     48
     49	return ffa_drv->probe(ffa_dev);
     50}
     51
     52static void ffa_device_remove(struct device *dev)
     53{
     54	struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
     55
     56	ffa_drv->remove(to_ffa_dev(dev));
     57}
     58
     59static int ffa_device_uevent(struct device *dev, struct kobj_uevent_env *env)
     60{
     61	struct ffa_device *ffa_dev = to_ffa_dev(dev);
     62
     63	return add_uevent_var(env, "MODALIAS=arm_ffa:%04x:%pUb",
     64			      ffa_dev->vm_id, &ffa_dev->uuid);
     65}
     66
     67static ssize_t partition_id_show(struct device *dev,
     68				 struct device_attribute *attr, char *buf)
     69{
     70	struct ffa_device *ffa_dev = to_ffa_dev(dev);
     71
     72	return sprintf(buf, "0x%04x\n", ffa_dev->vm_id);
     73}
     74static DEVICE_ATTR_RO(partition_id);
     75
     76static ssize_t uuid_show(struct device *dev, struct device_attribute *attr,
     77			 char *buf)
     78{
     79	struct ffa_device *ffa_dev = to_ffa_dev(dev);
     80
     81	return sprintf(buf, "%pUb\n", &ffa_dev->uuid);
     82}
     83static DEVICE_ATTR_RO(uuid);
     84
     85static struct attribute *ffa_device_attributes_attrs[] = {
     86	&dev_attr_partition_id.attr,
     87	&dev_attr_uuid.attr,
     88	NULL,
     89};
     90ATTRIBUTE_GROUPS(ffa_device_attributes);
     91
     92struct bus_type ffa_bus_type = {
     93	.name		= "arm_ffa",
     94	.match		= ffa_device_match,
     95	.probe		= ffa_device_probe,
     96	.remove		= ffa_device_remove,
     97	.uevent		= ffa_device_uevent,
     98	.dev_groups	= ffa_device_attributes_groups,
     99};
    100EXPORT_SYMBOL_GPL(ffa_bus_type);
    101
    102int ffa_driver_register(struct ffa_driver *driver, struct module *owner,
    103			const char *mod_name)
    104{
    105	int ret;
    106
    107	if (!driver->probe)
    108		return -EINVAL;
    109
    110	driver->driver.bus = &ffa_bus_type;
    111	driver->driver.name = driver->name;
    112	driver->driver.owner = owner;
    113	driver->driver.mod_name = mod_name;
    114
    115	ret = driver_register(&driver->driver);
    116	if (!ret)
    117		pr_debug("registered new ffa driver %s\n", driver->name);
    118
    119	return ret;
    120}
    121EXPORT_SYMBOL_GPL(ffa_driver_register);
    122
    123void ffa_driver_unregister(struct ffa_driver *driver)
    124{
    125	driver_unregister(&driver->driver);
    126}
    127EXPORT_SYMBOL_GPL(ffa_driver_unregister);
    128
    129static void ffa_release_device(struct device *dev)
    130{
    131	struct ffa_device *ffa_dev = to_ffa_dev(dev);
    132
    133	kfree(ffa_dev);
    134}
    135
    136static int __ffa_devices_unregister(struct device *dev, void *data)
    137{
    138	device_unregister(dev);
    139
    140	return 0;
    141}
    142
    143static void ffa_devices_unregister(void)
    144{
    145	bus_for_each_dev(&ffa_bus_type, NULL, NULL,
    146			 __ffa_devices_unregister);
    147}
    148
    149bool ffa_device_is_valid(struct ffa_device *ffa_dev)
    150{
    151	bool valid = false;
    152	struct device *dev = NULL;
    153	struct ffa_device *tmp_dev;
    154
    155	do {
    156		dev = bus_find_next_device(&ffa_bus_type, dev);
    157		tmp_dev = to_ffa_dev(dev);
    158		if (tmp_dev == ffa_dev) {
    159			valid = true;
    160			break;
    161		}
    162		put_device(dev);
    163	} while (dev);
    164
    165	put_device(dev);
    166
    167	return valid;
    168}
    169
    170struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id)
    171{
    172	int ret;
    173	struct device *dev;
    174	struct ffa_device *ffa_dev;
    175
    176	ffa_dev = kzalloc(sizeof(*ffa_dev), GFP_KERNEL);
    177	if (!ffa_dev)
    178		return NULL;
    179
    180	dev = &ffa_dev->dev;
    181	dev->bus = &ffa_bus_type;
    182	dev->release = ffa_release_device;
    183	dev_set_name(&ffa_dev->dev, "arm-ffa-%04x", vm_id);
    184
    185	ffa_dev->vm_id = vm_id;
    186	uuid_copy(&ffa_dev->uuid, uuid);
    187
    188	ret = device_register(&ffa_dev->dev);
    189	if (ret) {
    190		dev_err(dev, "unable to register device %s err=%d\n",
    191			dev_name(dev), ret);
    192		put_device(dev);
    193		return NULL;
    194	}
    195
    196	return ffa_dev;
    197}
    198EXPORT_SYMBOL_GPL(ffa_device_register);
    199
    200void ffa_device_unregister(struct ffa_device *ffa_dev)
    201{
    202	if (!ffa_dev)
    203		return;
    204
    205	device_unregister(&ffa_dev->dev);
    206}
    207EXPORT_SYMBOL_GPL(ffa_device_unregister);
    208
    209int arm_ffa_bus_init(void)
    210{
    211	return bus_register(&ffa_bus_type);
    212}
    213
    214void arm_ffa_bus_exit(void)
    215{
    216	ffa_devices_unregister();
    217	bus_unregister(&ffa_bus_type);
    218}