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

network.c (13915B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *
      4 * arch/xtensa/platforms/iss/network.c
      5 *
      6 * Platform specific initialization.
      7 *
      8 * Authors: Chris Zankel <chris@zankel.net>
      9 * Based on work form the UML team.
     10 *
     11 * Copyright 2005 Tensilica Inc.
     12 */
     13
     14#define pr_fmt(fmt) "%s: " fmt, __func__
     15
     16#include <linux/list.h>
     17#include <linux/irq.h>
     18#include <linux/spinlock.h>
     19#include <linux/slab.h>
     20#include <linux/timer.h>
     21#include <linux/if_ether.h>
     22#include <linux/inetdevice.h>
     23#include <linux/init.h>
     24#include <linux/if_tun.h>
     25#include <linux/etherdevice.h>
     26#include <linux/interrupt.h>
     27#include <linux/ioctl.h>
     28#include <linux/memblock.h>
     29#include <linux/ethtool.h>
     30#include <linux/rtnetlink.h>
     31#include <linux/platform_device.h>
     32
     33#include <platform/simcall.h>
     34
     35#define DRIVER_NAME "iss-netdev"
     36#define ETH_MAX_PACKET 1500
     37#define ETH_HEADER_OTHER 14
     38#define ISS_NET_TIMER_VALUE (HZ / 10)
     39
     40
     41static DEFINE_SPINLOCK(devices_lock);
     42static LIST_HEAD(devices);
     43
     44/* ------------------------------------------------------------------------- */
     45
     46/* We currently only support the TUNTAP transport protocol. */
     47
     48#define TRANSPORT_TUNTAP_NAME "tuntap"
     49#define TRANSPORT_TUNTAP_MTU ETH_MAX_PACKET
     50
     51struct tuntap_info {
     52	char dev_name[IFNAMSIZ];
     53	int fd;
     54};
     55
     56/* ------------------------------------------------------------------------- */
     57
     58
     59struct iss_net_private;
     60
     61struct iss_net_ops {
     62	int (*open)(struct iss_net_private *lp);
     63	void (*close)(struct iss_net_private *lp);
     64	int (*read)(struct iss_net_private *lp, struct sk_buff **skb);
     65	int (*write)(struct iss_net_private *lp, struct sk_buff **skb);
     66	unsigned short (*protocol)(struct sk_buff *skb);
     67	int (*poll)(struct iss_net_private *lp);
     68};
     69
     70/* This structure contains out private information for the driver. */
     71
     72struct iss_net_private {
     73	struct list_head device_list;
     74
     75	spinlock_t lock;
     76	struct net_device *dev;
     77	struct platform_device pdev;
     78	struct timer_list tl;
     79	struct rtnl_link_stats64 stats;
     80
     81	struct timer_list timer;
     82	unsigned int timer_val;
     83
     84	int index;
     85	int mtu;
     86
     87	struct {
     88		union {
     89			struct tuntap_info tuntap;
     90		} info;
     91
     92		const struct iss_net_ops *net_ops;
     93	} tp;
     94
     95};
     96
     97/* ================================ HELPERS ================================ */
     98
     99
    100static char *split_if_spec(char *str, ...)
    101{
    102	char **arg, *end;
    103	va_list ap;
    104
    105	va_start(ap, str);
    106	while ((arg = va_arg(ap, char**)) != NULL) {
    107		if (*str == '\0') {
    108			va_end(ap);
    109			return NULL;
    110		}
    111		end = strchr(str, ',');
    112		if (end != str)
    113			*arg = str;
    114		if (end == NULL) {
    115			va_end(ap);
    116			return NULL;
    117		}
    118		*end++ = '\0';
    119		str = end;
    120	}
    121	va_end(ap);
    122	return str;
    123}
    124
    125/* Set Ethernet address of the specified device. */
    126
    127static void setup_etheraddr(struct net_device *dev, char *str)
    128{
    129	u8 addr[ETH_ALEN];
    130
    131	if (str == NULL)
    132		goto random;
    133
    134	if (!mac_pton(str, addr)) {
    135		pr_err("%s: failed to parse '%s' as an ethernet address\n",
    136		       dev->name, str);
    137		goto random;
    138	}
    139	if (is_multicast_ether_addr(addr)) {
    140		pr_err("%s: attempt to assign a multicast ethernet address\n",
    141		       dev->name);
    142		goto random;
    143	}
    144	if (!is_valid_ether_addr(addr)) {
    145		pr_err("%s: attempt to assign an invalid ethernet address\n",
    146		       dev->name);
    147		goto random;
    148	}
    149	if (!is_local_ether_addr(addr))
    150		pr_warn("%s: assigning a globally valid ethernet address\n",
    151			dev->name);
    152	eth_hw_addr_set(dev, addr);
    153	return;
    154
    155random:
    156	pr_info("%s: choosing a random ethernet address\n",
    157		dev->name);
    158	eth_hw_addr_random(dev);
    159}
    160
    161/* ======================= TUNTAP TRANSPORT INTERFACE ====================== */
    162
    163static int tuntap_open(struct iss_net_private *lp)
    164{
    165	struct ifreq ifr;
    166	char *dev_name = lp->tp.info.tuntap.dev_name;
    167	int err = -EINVAL;
    168	int fd;
    169
    170	fd = simc_open("/dev/net/tun", 02, 0); /* O_RDWR */
    171	if (fd < 0) {
    172		pr_err("%s: failed to open /dev/net/tun, returned %d (errno = %d)\n",
    173		       lp->dev->name, fd, errno);
    174		return fd;
    175	}
    176
    177	memset(&ifr, 0, sizeof(ifr));
    178	ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
    179	strscpy(ifr.ifr_name, dev_name, sizeof(ifr.ifr_name));
    180
    181	err = simc_ioctl(fd, TUNSETIFF, &ifr);
    182	if (err < 0) {
    183		pr_err("%s: failed to set interface %s, returned %d (errno = %d)\n",
    184		       lp->dev->name, dev_name, err, errno);
    185		simc_close(fd);
    186		return err;
    187	}
    188
    189	lp->tp.info.tuntap.fd = fd;
    190	return err;
    191}
    192
    193static void tuntap_close(struct iss_net_private *lp)
    194{
    195	simc_close(lp->tp.info.tuntap.fd);
    196	lp->tp.info.tuntap.fd = -1;
    197}
    198
    199static int tuntap_read(struct iss_net_private *lp, struct sk_buff **skb)
    200{
    201	return simc_read(lp->tp.info.tuntap.fd,
    202			(*skb)->data, (*skb)->dev->mtu + ETH_HEADER_OTHER);
    203}
    204
    205static int tuntap_write(struct iss_net_private *lp, struct sk_buff **skb)
    206{
    207	return simc_write(lp->tp.info.tuntap.fd, (*skb)->data, (*skb)->len);
    208}
    209
    210unsigned short tuntap_protocol(struct sk_buff *skb)
    211{
    212	return eth_type_trans(skb, skb->dev);
    213}
    214
    215static int tuntap_poll(struct iss_net_private *lp)
    216{
    217	return simc_poll(lp->tp.info.tuntap.fd);
    218}
    219
    220static const struct iss_net_ops tuntap_ops = {
    221	.open		= tuntap_open,
    222	.close		= tuntap_close,
    223	.read		= tuntap_read,
    224	.write		= tuntap_write,
    225	.protocol	= tuntap_protocol,
    226	.poll		= tuntap_poll,
    227};
    228
    229/*
    230 * ethX=tuntap,[mac address],device name
    231 */
    232
    233static int tuntap_probe(struct iss_net_private *lp, int index, char *init)
    234{
    235	struct net_device *dev = lp->dev;
    236	char *dev_name = NULL, *mac_str = NULL, *rem = NULL;
    237
    238	/* Transport should be 'tuntap': ethX=tuntap,mac,dev_name */
    239
    240	if (strncmp(init, TRANSPORT_TUNTAP_NAME,
    241		    sizeof(TRANSPORT_TUNTAP_NAME) - 1))
    242		return 0;
    243
    244	init += sizeof(TRANSPORT_TUNTAP_NAME) - 1;
    245	if (*init == ',') {
    246		rem = split_if_spec(init + 1, &mac_str, &dev_name);
    247		if (rem != NULL) {
    248			pr_err("%s: extra garbage on specification : '%s'\n",
    249			       dev->name, rem);
    250			return 0;
    251		}
    252	} else if (*init != '\0') {
    253		pr_err("%s: invalid argument: %s. Skipping device!\n",
    254		       dev->name, init);
    255		return 0;
    256	}
    257
    258	if (!dev_name) {
    259		pr_err("%s: missing tuntap device name\n", dev->name);
    260		return 0;
    261	}
    262
    263	strscpy(lp->tp.info.tuntap.dev_name, dev_name,
    264		sizeof(lp->tp.info.tuntap.dev_name));
    265
    266	setup_etheraddr(dev, mac_str);
    267
    268	lp->mtu = TRANSPORT_TUNTAP_MTU;
    269
    270	lp->tp.info.tuntap.fd = -1;
    271	lp->tp.net_ops = &tuntap_ops;
    272
    273	return 1;
    274}
    275
    276/* ================================ ISS NET ================================ */
    277
    278static int iss_net_rx(struct net_device *dev)
    279{
    280	struct iss_net_private *lp = netdev_priv(dev);
    281	int pkt_len;
    282	struct sk_buff *skb;
    283
    284	/* Check if there is any new data. */
    285
    286	if (lp->tp.net_ops->poll(lp) == 0)
    287		return 0;
    288
    289	/* Try to allocate memory, if it fails, try again next round. */
    290
    291	skb = dev_alloc_skb(dev->mtu + 2 + ETH_HEADER_OTHER);
    292	if (skb == NULL) {
    293		spin_lock_bh(&lp->lock);
    294		lp->stats.rx_dropped++;
    295		spin_unlock_bh(&lp->lock);
    296		return 0;
    297	}
    298
    299	skb_reserve(skb, 2);
    300
    301	/* Setup skb */
    302
    303	skb->dev = dev;
    304	skb_reset_mac_header(skb);
    305	pkt_len = lp->tp.net_ops->read(lp, &skb);
    306	skb_put(skb, pkt_len);
    307
    308	if (pkt_len > 0) {
    309		skb_trim(skb, pkt_len);
    310		skb->protocol = lp->tp.net_ops->protocol(skb);
    311
    312		spin_lock_bh(&lp->lock);
    313		lp->stats.rx_bytes += skb->len;
    314		lp->stats.rx_packets++;
    315		spin_unlock_bh(&lp->lock);
    316		netif_rx(skb);
    317		return pkt_len;
    318	}
    319	kfree_skb(skb);
    320	return pkt_len;
    321}
    322
    323static int iss_net_poll(struct iss_net_private *lp)
    324{
    325	int err, ret = 0;
    326
    327	if (!netif_running(lp->dev))
    328		return 0;
    329
    330	while ((err = iss_net_rx(lp->dev)) > 0)
    331		ret++;
    332
    333	if (err < 0) {
    334		pr_err("Device '%s' read returned %d, shutting it down\n",
    335		       lp->dev->name, err);
    336		dev_close(lp->dev);
    337	} else {
    338		/* FIXME reactivate_fd(lp->fd, ISS_ETH_IRQ); */
    339	}
    340
    341	return ret;
    342}
    343
    344
    345static void iss_net_timer(struct timer_list *t)
    346{
    347	struct iss_net_private *lp = from_timer(lp, t, timer);
    348
    349	iss_net_poll(lp);
    350	mod_timer(&lp->timer, jiffies + lp->timer_val);
    351}
    352
    353
    354static int iss_net_open(struct net_device *dev)
    355{
    356	struct iss_net_private *lp = netdev_priv(dev);
    357	int err;
    358
    359	err = lp->tp.net_ops->open(lp);
    360	if (err < 0)
    361		return err;
    362
    363	netif_start_queue(dev);
    364
    365	/* clear buffer - it can happen that the host side of the interface
    366	 * is full when we get here. In this case, new data is never queued,
    367	 * SIGIOs never arrive, and the net never works.
    368	 */
    369	while ((err = iss_net_rx(dev)) > 0)
    370		;
    371
    372	timer_setup(&lp->timer, iss_net_timer, 0);
    373	lp->timer_val = ISS_NET_TIMER_VALUE;
    374	mod_timer(&lp->timer, jiffies + lp->timer_val);
    375
    376	return err;
    377}
    378
    379static int iss_net_close(struct net_device *dev)
    380{
    381	struct iss_net_private *lp = netdev_priv(dev);
    382
    383	netif_stop_queue(dev);
    384	del_timer_sync(&lp->timer);
    385	lp->tp.net_ops->close(lp);
    386
    387	return 0;
    388}
    389
    390static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
    391{
    392	struct iss_net_private *lp = netdev_priv(dev);
    393	int len;
    394
    395	netif_stop_queue(dev);
    396
    397	len = lp->tp.net_ops->write(lp, &skb);
    398
    399	if (len == skb->len) {
    400		spin_lock_bh(&lp->lock);
    401		lp->stats.tx_packets++;
    402		lp->stats.tx_bytes += skb->len;
    403		spin_unlock_bh(&lp->lock);
    404		netif_trans_update(dev);
    405		netif_start_queue(dev);
    406
    407		/* this is normally done in the interrupt when tx finishes */
    408		netif_wake_queue(dev);
    409
    410	} else if (len == 0) {
    411		netif_start_queue(dev);
    412		spin_lock_bh(&lp->lock);
    413		lp->stats.tx_dropped++;
    414		spin_unlock_bh(&lp->lock);
    415
    416	} else {
    417		netif_start_queue(dev);
    418		pr_err("%s: %s failed(%d)\n", dev->name, __func__, len);
    419	}
    420
    421
    422	dev_kfree_skb(skb);
    423	return NETDEV_TX_OK;
    424}
    425
    426
    427static void iss_net_get_stats64(struct net_device *dev,
    428				struct rtnl_link_stats64 *stats)
    429{
    430	struct iss_net_private *lp = netdev_priv(dev);
    431
    432	spin_lock_bh(&lp->lock);
    433	*stats = lp->stats;
    434	spin_unlock_bh(&lp->lock);
    435}
    436
    437static void iss_net_set_multicast_list(struct net_device *dev)
    438{
    439}
    440
    441static void iss_net_tx_timeout(struct net_device *dev, unsigned int txqueue)
    442{
    443}
    444
    445static int iss_net_change_mtu(struct net_device *dev, int new_mtu)
    446{
    447	return -EINVAL;
    448}
    449
    450void iss_net_user_timer_expire(struct timer_list *unused)
    451{
    452}
    453
    454
    455static struct platform_driver iss_net_driver = {
    456	.driver = {
    457		.name  = DRIVER_NAME,
    458	},
    459};
    460
    461static int driver_registered;
    462
    463static const struct net_device_ops iss_netdev_ops = {
    464	.ndo_open		= iss_net_open,
    465	.ndo_stop		= iss_net_close,
    466	.ndo_get_stats64	= iss_net_get_stats64,
    467	.ndo_start_xmit		= iss_net_start_xmit,
    468	.ndo_validate_addr	= eth_validate_addr,
    469	.ndo_change_mtu		= iss_net_change_mtu,
    470	.ndo_set_mac_address	= eth_mac_addr,
    471	.ndo_tx_timeout		= iss_net_tx_timeout,
    472	.ndo_set_rx_mode	= iss_net_set_multicast_list,
    473};
    474
    475static int iss_net_configure(int index, char *init)
    476{
    477	struct net_device *dev;
    478	struct iss_net_private *lp;
    479	int err;
    480
    481	dev = alloc_etherdev(sizeof(*lp));
    482	if (dev == NULL) {
    483		pr_err("eth_configure: failed to allocate device\n");
    484		return 1;
    485	}
    486
    487	/* Initialize private element. */
    488
    489	lp = netdev_priv(dev);
    490	*lp = (struct iss_net_private) {
    491		.device_list		= LIST_HEAD_INIT(lp->device_list),
    492		.dev			= dev,
    493		.index			= index,
    494	};
    495
    496	spin_lock_init(&lp->lock);
    497	/*
    498	 * If this name ends up conflicting with an existing registered
    499	 * netdevice, that is OK, register_netdev{,ice}() will notice this
    500	 * and fail.
    501	 */
    502	snprintf(dev->name, sizeof(dev->name), "eth%d", index);
    503
    504	/*
    505	 * Try all transport protocols.
    506	 * Note: more protocols can be added by adding '&& !X_init(lp, eth)'.
    507	 */
    508
    509	if (!tuntap_probe(lp, index, init)) {
    510		pr_err("%s: invalid arguments. Skipping device!\n",
    511		       dev->name);
    512		goto errout;
    513	}
    514
    515	pr_info("Netdevice %d (%pM)\n", index, dev->dev_addr);
    516
    517	/* sysfs register */
    518
    519	if (!driver_registered) {
    520		platform_driver_register(&iss_net_driver);
    521		driver_registered = 1;
    522	}
    523
    524	spin_lock(&devices_lock);
    525	list_add(&lp->device_list, &devices);
    526	spin_unlock(&devices_lock);
    527
    528	lp->pdev.id = index;
    529	lp->pdev.name = DRIVER_NAME;
    530	platform_device_register(&lp->pdev);
    531	SET_NETDEV_DEV(dev, &lp->pdev.dev);
    532
    533	dev->netdev_ops = &iss_netdev_ops;
    534	dev->mtu = lp->mtu;
    535	dev->watchdog_timeo = (HZ >> 1);
    536	dev->irq = -1;
    537
    538	rtnl_lock();
    539	err = register_netdevice(dev);
    540	rtnl_unlock();
    541
    542	if (err) {
    543		pr_err("%s: error registering net device!\n", dev->name);
    544		/* XXX: should we call ->remove() here? */
    545		free_netdev(dev);
    546		return 1;
    547	}
    548
    549	timer_setup(&lp->tl, iss_net_user_timer_expire, 0);
    550
    551	return 0;
    552
    553errout:
    554	/* FIXME: unregister; free, etc.. */
    555	return -EIO;
    556}
    557
    558/* ------------------------------------------------------------------------- */
    559
    560/* Filled in during early boot */
    561
    562struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line);
    563
    564struct iss_net_init {
    565	struct list_head list;
    566	char *init;		/* init string */
    567	int index;
    568};
    569
    570/*
    571 * Parse the command line and look for 'ethX=...' fields, and register all
    572 * those fields. They will be later initialized in iss_net_init.
    573 */
    574
    575static int __init iss_net_setup(char *str)
    576{
    577	struct iss_net_private *device = NULL;
    578	struct iss_net_init *new;
    579	struct list_head *ele;
    580	char *end;
    581	int rc;
    582	unsigned n;
    583
    584	end = strchr(str, '=');
    585	if (!end) {
    586		pr_err("Expected '=' after device number\n");
    587		return 1;
    588	}
    589	*end = 0;
    590	rc = kstrtouint(str, 0, &n);
    591	*end = '=';
    592	if (rc < 0) {
    593		pr_err("Failed to parse '%s'\n", str);
    594		return 1;
    595	}
    596	str = end;
    597
    598	spin_lock(&devices_lock);
    599
    600	list_for_each(ele, &devices) {
    601		device = list_entry(ele, struct iss_net_private, device_list);
    602		if (device->index == n)
    603			break;
    604	}
    605
    606	spin_unlock(&devices_lock);
    607
    608	if (device && device->index == n) {
    609		pr_err("Device %u already configured\n", n);
    610		return 1;
    611	}
    612
    613	new = memblock_alloc(sizeof(*new), SMP_CACHE_BYTES);
    614	if (new == NULL) {
    615		pr_err("Alloc_bootmem failed\n");
    616		return 1;
    617	}
    618
    619	INIT_LIST_HEAD(&new->list);
    620	new->index = n;
    621	new->init = str + 1;
    622
    623	list_add_tail(&new->list, &eth_cmd_line);
    624	return 1;
    625}
    626
    627__setup("eth", iss_net_setup);
    628
    629/*
    630 * Initialize all ISS Ethernet devices previously registered in iss_net_setup.
    631 */
    632
    633static int iss_net_init(void)
    634{
    635	struct list_head *ele, *next;
    636
    637	/* Walk through all Ethernet devices specified in the command line. */
    638
    639	list_for_each_safe(ele, next, &eth_cmd_line) {
    640		struct iss_net_init *eth;
    641		eth = list_entry(ele, struct iss_net_init, list);
    642		iss_net_configure(eth->index, eth->init);
    643	}
    644
    645	return 1;
    646}
    647device_initcall(iss_net_init);