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 (8913B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright (C) 2017 Netronome Systems, Inc.
      3 * Copyright (C) 2019 Mellanox Technologies. All rights reserved
      4 */
      5
      6#include <linux/device.h>
      7#include <linux/idr.h>
      8#include <linux/kernel.h>
      9#include <linux/list.h>
     10#include <linux/mutex.h>
     11#include <linux/slab.h>
     12#include <linux/sysfs.h>
     13
     14#include "netdevsim.h"
     15
     16static DEFINE_IDA(nsim_bus_dev_ids);
     17static LIST_HEAD(nsim_bus_dev_list);
     18static DEFINE_MUTEX(nsim_bus_dev_list_lock);
     19static bool nsim_bus_enable;
     20
     21static struct nsim_bus_dev *to_nsim_bus_dev(struct device *dev)
     22{
     23	return container_of(dev, struct nsim_bus_dev, dev);
     24}
     25
     26static ssize_t
     27nsim_bus_dev_numvfs_store(struct device *dev, struct device_attribute *attr,
     28			  const char *buf, size_t count)
     29{
     30	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
     31	unsigned int num_vfs;
     32	int ret;
     33
     34	ret = kstrtouint(buf, 0, &num_vfs);
     35	if (ret)
     36		return ret;
     37
     38	device_lock(dev);
     39	ret = -ENOENT;
     40	if (dev_get_drvdata(dev))
     41		ret = nsim_drv_configure_vfs(nsim_bus_dev, num_vfs);
     42	device_unlock(dev);
     43
     44	return ret ? ret : count;
     45}
     46
     47static ssize_t
     48nsim_bus_dev_numvfs_show(struct device *dev,
     49			 struct device_attribute *attr, char *buf)
     50{
     51	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
     52
     53	return sprintf(buf, "%u\n", nsim_bus_dev->num_vfs);
     54}
     55
     56static struct device_attribute nsim_bus_dev_numvfs_attr =
     57	__ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show,
     58	       nsim_bus_dev_numvfs_store);
     59
     60static ssize_t
     61new_port_store(struct device *dev, struct device_attribute *attr,
     62	       const char *buf, size_t count)
     63{
     64	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
     65	unsigned int port_index;
     66	int ret;
     67
     68	/* Prevent to use nsim_bus_dev before initialization. */
     69	if (!smp_load_acquire(&nsim_bus_dev->init))
     70		return -EBUSY;
     71	ret = kstrtouint(buf, 0, &port_index);
     72	if (ret)
     73		return ret;
     74
     75	if (!mutex_trylock(&nsim_bus_dev->nsim_bus_reload_lock))
     76		return -EBUSY;
     77
     78	if (nsim_bus_dev->in_reload) {
     79		mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
     80		return -EBUSY;
     81	}
     82
     83	ret = nsim_drv_port_add(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index);
     84	mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
     85	return ret ? ret : count;
     86}
     87
     88static struct device_attribute nsim_bus_dev_new_port_attr = __ATTR_WO(new_port);
     89
     90static ssize_t
     91del_port_store(struct device *dev, struct device_attribute *attr,
     92	       const char *buf, size_t count)
     93{
     94	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
     95	unsigned int port_index;
     96	int ret;
     97
     98	/* Prevent to use nsim_bus_dev before initialization. */
     99	if (!smp_load_acquire(&nsim_bus_dev->init))
    100		return -EBUSY;
    101	ret = kstrtouint(buf, 0, &port_index);
    102	if (ret)
    103		return ret;
    104
    105	if (!mutex_trylock(&nsim_bus_dev->nsim_bus_reload_lock))
    106		return -EBUSY;
    107
    108	if (nsim_bus_dev->in_reload) {
    109		mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
    110		return -EBUSY;
    111	}
    112
    113	ret = nsim_drv_port_del(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index);
    114	mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock);
    115	return ret ? ret : count;
    116}
    117
    118static struct device_attribute nsim_bus_dev_del_port_attr = __ATTR_WO(del_port);
    119
    120static struct attribute *nsim_bus_dev_attrs[] = {
    121	&nsim_bus_dev_numvfs_attr.attr,
    122	&nsim_bus_dev_new_port_attr.attr,
    123	&nsim_bus_dev_del_port_attr.attr,
    124	NULL,
    125};
    126
    127static const struct attribute_group nsim_bus_dev_attr_group = {
    128	.attrs = nsim_bus_dev_attrs,
    129};
    130
    131static const struct attribute_group *nsim_bus_dev_attr_groups[] = {
    132	&nsim_bus_dev_attr_group,
    133	NULL,
    134};
    135
    136static void nsim_bus_dev_release(struct device *dev)
    137{
    138}
    139
    140static struct device_type nsim_bus_dev_type = {
    141	.groups = nsim_bus_dev_attr_groups,
    142	.release = nsim_bus_dev_release,
    143};
    144
    145static struct nsim_bus_dev *
    146nsim_bus_dev_new(unsigned int id, unsigned int port_count, unsigned int num_queues);
    147
    148static ssize_t
    149new_device_store(struct bus_type *bus, const char *buf, size_t count)
    150{
    151	unsigned int id, port_count, num_queues;
    152	struct nsim_bus_dev *nsim_bus_dev;
    153	int err;
    154
    155	err = sscanf(buf, "%u %u %u", &id, &port_count, &num_queues);
    156	switch (err) {
    157	case 1:
    158		port_count = 1;
    159		fallthrough;
    160	case 2:
    161		num_queues = 1;
    162		fallthrough;
    163	case 3:
    164		if (id > INT_MAX) {
    165			pr_err("Value of \"id\" is too big.\n");
    166			return -EINVAL;
    167		}
    168		break;
    169	default:
    170		pr_err("Format for adding new device is \"id port_count num_queues\" (uint uint unit).\n");
    171		return -EINVAL;
    172	}
    173
    174	mutex_lock(&nsim_bus_dev_list_lock);
    175	/* Prevent to use resource before initialization. */
    176	if (!smp_load_acquire(&nsim_bus_enable)) {
    177		err = -EBUSY;
    178		goto err;
    179	}
    180
    181	nsim_bus_dev = nsim_bus_dev_new(id, port_count, num_queues);
    182	if (IS_ERR(nsim_bus_dev)) {
    183		err = PTR_ERR(nsim_bus_dev);
    184		goto err;
    185	}
    186
    187	/* Allow using nsim_bus_dev */
    188	smp_store_release(&nsim_bus_dev->init, true);
    189
    190	list_add_tail(&nsim_bus_dev->list, &nsim_bus_dev_list);
    191	mutex_unlock(&nsim_bus_dev_list_lock);
    192
    193	return count;
    194err:
    195	mutex_unlock(&nsim_bus_dev_list_lock);
    196	return err;
    197}
    198static BUS_ATTR_WO(new_device);
    199
    200static void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev);
    201
    202static ssize_t
    203del_device_store(struct bus_type *bus, const char *buf, size_t count)
    204{
    205	struct nsim_bus_dev *nsim_bus_dev, *tmp;
    206	unsigned int id;
    207	int err;
    208
    209	err = sscanf(buf, "%u", &id);
    210	switch (err) {
    211	case 1:
    212		if (id > INT_MAX) {
    213			pr_err("Value of \"id\" is too big.\n");
    214			return -EINVAL;
    215		}
    216		break;
    217	default:
    218		pr_err("Format for deleting device is \"id\" (uint).\n");
    219		return -EINVAL;
    220	}
    221
    222	err = -ENOENT;
    223	mutex_lock(&nsim_bus_dev_list_lock);
    224	/* Prevent to use resource before initialization. */
    225	if (!smp_load_acquire(&nsim_bus_enable)) {
    226		mutex_unlock(&nsim_bus_dev_list_lock);
    227		return -EBUSY;
    228	}
    229	list_for_each_entry_safe(nsim_bus_dev, tmp, &nsim_bus_dev_list, list) {
    230		if (nsim_bus_dev->dev.id != id)
    231			continue;
    232		list_del(&nsim_bus_dev->list);
    233		nsim_bus_dev_del(nsim_bus_dev);
    234		err = 0;
    235		break;
    236	}
    237	mutex_unlock(&nsim_bus_dev_list_lock);
    238	return !err ? count : err;
    239}
    240static BUS_ATTR_WO(del_device);
    241
    242static struct attribute *nsim_bus_attrs[] = {
    243	&bus_attr_new_device.attr,
    244	&bus_attr_del_device.attr,
    245	NULL
    246};
    247ATTRIBUTE_GROUPS(nsim_bus);
    248
    249static int nsim_bus_probe(struct device *dev)
    250{
    251	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
    252
    253	return nsim_drv_probe(nsim_bus_dev);
    254}
    255
    256static void nsim_bus_remove(struct device *dev)
    257{
    258	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
    259
    260	nsim_drv_remove(nsim_bus_dev);
    261}
    262
    263static int nsim_num_vf(struct device *dev)
    264{
    265	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
    266
    267	return nsim_bus_dev->num_vfs;
    268}
    269
    270static struct bus_type nsim_bus = {
    271	.name		= DRV_NAME,
    272	.dev_name	= DRV_NAME,
    273	.bus_groups	= nsim_bus_groups,
    274	.probe		= nsim_bus_probe,
    275	.remove		= nsim_bus_remove,
    276	.num_vf		= nsim_num_vf,
    277};
    278
    279#define NSIM_BUS_DEV_MAX_VFS 4
    280
    281static struct nsim_bus_dev *
    282nsim_bus_dev_new(unsigned int id, unsigned int port_count, unsigned int num_queues)
    283{
    284	struct nsim_bus_dev *nsim_bus_dev;
    285	int err;
    286
    287	nsim_bus_dev = kzalloc(sizeof(*nsim_bus_dev), GFP_KERNEL);
    288	if (!nsim_bus_dev)
    289		return ERR_PTR(-ENOMEM);
    290
    291	err = ida_alloc_range(&nsim_bus_dev_ids, id, id, GFP_KERNEL);
    292	if (err < 0)
    293		goto err_nsim_bus_dev_free;
    294	nsim_bus_dev->dev.id = err;
    295	nsim_bus_dev->dev.bus = &nsim_bus;
    296	nsim_bus_dev->dev.type = &nsim_bus_dev_type;
    297	nsim_bus_dev->port_count = port_count;
    298	nsim_bus_dev->num_queues = num_queues;
    299	nsim_bus_dev->initial_net = current->nsproxy->net_ns;
    300	nsim_bus_dev->max_vfs = NSIM_BUS_DEV_MAX_VFS;
    301	mutex_init(&nsim_bus_dev->nsim_bus_reload_lock);
    302	/* Disallow using nsim_bus_dev */
    303	smp_store_release(&nsim_bus_dev->init, false);
    304
    305	err = device_register(&nsim_bus_dev->dev);
    306	if (err)
    307		goto err_nsim_bus_dev_id_free;
    308
    309	return nsim_bus_dev;
    310
    311err_nsim_bus_dev_id_free:
    312	ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id);
    313err_nsim_bus_dev_free:
    314	kfree(nsim_bus_dev);
    315	return ERR_PTR(err);
    316}
    317
    318static void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev)
    319{
    320	/* Disallow using nsim_bus_dev */
    321	smp_store_release(&nsim_bus_dev->init, false);
    322	device_unregister(&nsim_bus_dev->dev);
    323	ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id);
    324	kfree(nsim_bus_dev);
    325}
    326
    327static struct device_driver nsim_driver = {
    328	.name		= DRV_NAME,
    329	.bus		= &nsim_bus,
    330	.owner		= THIS_MODULE,
    331};
    332
    333int nsim_bus_init(void)
    334{
    335	int err;
    336
    337	err = bus_register(&nsim_bus);
    338	if (err)
    339		return err;
    340	err = driver_register(&nsim_driver);
    341	if (err)
    342		goto err_bus_unregister;
    343	/* Allow using resources */
    344	smp_store_release(&nsim_bus_enable, true);
    345	return 0;
    346
    347err_bus_unregister:
    348	bus_unregister(&nsim_bus);
    349	return err;
    350}
    351
    352void nsim_bus_exit(void)
    353{
    354	struct nsim_bus_dev *nsim_bus_dev, *tmp;
    355
    356	/* Disallow using resources */
    357	smp_store_release(&nsim_bus_enable, false);
    358
    359	mutex_lock(&nsim_bus_dev_list_lock);
    360	list_for_each_entry_safe(nsim_bus_dev, tmp, &nsim_bus_dev_list, list) {
    361		list_del(&nsim_bus_dev->list);
    362		nsim_bus_dev_del(nsim_bus_dev);
    363	}
    364	mutex_unlock(&nsim_bus_dev_list_lock);
    365
    366	driver_unregister(&nsim_driver);
    367	bus_unregister(&nsim_bus);
    368}