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

trans_xen.c (13085B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * linux/fs/9p/trans_xen
      4 *
      5 * Xen transport layer.
      6 *
      7 * Copyright (C) 2017 by Stefano Stabellini <stefano@aporeto.com>
      8 */
      9
     10#include <xen/events.h>
     11#include <xen/grant_table.h>
     12#include <xen/xen.h>
     13#include <xen/xenbus.h>
     14#include <xen/interface/io/9pfs.h>
     15
     16#include <linux/module.h>
     17#include <linux/spinlock.h>
     18#include <net/9p/9p.h>
     19#include <net/9p/client.h>
     20#include <net/9p/transport.h>
     21
     22#define XEN_9PFS_NUM_RINGS 2
     23#define XEN_9PFS_RING_ORDER 9
     24#define XEN_9PFS_RING_SIZE(ring)  XEN_FLEX_RING_SIZE(ring->intf->ring_order)
     25
     26struct xen_9pfs_header {
     27	uint32_t size;
     28	uint8_t id;
     29	uint16_t tag;
     30
     31	/* uint8_t sdata[]; */
     32} __attribute__((packed));
     33
     34/* One per ring, more than one per 9pfs share */
     35struct xen_9pfs_dataring {
     36	struct xen_9pfs_front_priv *priv;
     37
     38	struct xen_9pfs_data_intf *intf;
     39	grant_ref_t ref;
     40	int evtchn;
     41	int irq;
     42	/* protect a ring from concurrent accesses */
     43	spinlock_t lock;
     44
     45	struct xen_9pfs_data data;
     46	wait_queue_head_t wq;
     47	struct work_struct work;
     48};
     49
     50/* One per 9pfs share */
     51struct xen_9pfs_front_priv {
     52	struct list_head list;
     53	struct xenbus_device *dev;
     54	char *tag;
     55	struct p9_client *client;
     56
     57	int num_rings;
     58	struct xen_9pfs_dataring *rings;
     59};
     60
     61static LIST_HEAD(xen_9pfs_devs);
     62static DEFINE_RWLOCK(xen_9pfs_lock);
     63
     64/* We don't currently allow canceling of requests */
     65static int p9_xen_cancel(struct p9_client *client, struct p9_req_t *req)
     66{
     67	return 1;
     68}
     69
     70static int p9_xen_create(struct p9_client *client, const char *addr, char *args)
     71{
     72	struct xen_9pfs_front_priv *priv;
     73
     74	if (addr == NULL)
     75		return -EINVAL;
     76
     77	read_lock(&xen_9pfs_lock);
     78	list_for_each_entry(priv, &xen_9pfs_devs, list) {
     79		if (!strcmp(priv->tag, addr)) {
     80			priv->client = client;
     81			read_unlock(&xen_9pfs_lock);
     82			return 0;
     83		}
     84	}
     85	read_unlock(&xen_9pfs_lock);
     86	return -EINVAL;
     87}
     88
     89static void p9_xen_close(struct p9_client *client)
     90{
     91	struct xen_9pfs_front_priv *priv;
     92
     93	read_lock(&xen_9pfs_lock);
     94	list_for_each_entry(priv, &xen_9pfs_devs, list) {
     95		if (priv->client == client) {
     96			priv->client = NULL;
     97			read_unlock(&xen_9pfs_lock);
     98			return;
     99		}
    100	}
    101	read_unlock(&xen_9pfs_lock);
    102}
    103
    104static bool p9_xen_write_todo(struct xen_9pfs_dataring *ring, RING_IDX size)
    105{
    106	RING_IDX cons, prod;
    107
    108	cons = ring->intf->out_cons;
    109	prod = ring->intf->out_prod;
    110	virt_mb();
    111
    112	return XEN_9PFS_RING_SIZE(ring) -
    113		xen_9pfs_queued(prod, cons, XEN_9PFS_RING_SIZE(ring)) >= size;
    114}
    115
    116static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
    117{
    118	struct xen_9pfs_front_priv *priv;
    119	RING_IDX cons, prod, masked_cons, masked_prod;
    120	unsigned long flags;
    121	u32 size = p9_req->tc.size;
    122	struct xen_9pfs_dataring *ring;
    123	int num;
    124
    125	read_lock(&xen_9pfs_lock);
    126	list_for_each_entry(priv, &xen_9pfs_devs, list) {
    127		if (priv->client == client)
    128			break;
    129	}
    130	read_unlock(&xen_9pfs_lock);
    131	if (list_entry_is_head(priv, &xen_9pfs_devs, list))
    132		return -EINVAL;
    133
    134	num = p9_req->tc.tag % priv->num_rings;
    135	ring = &priv->rings[num];
    136
    137again:
    138	while (wait_event_killable(ring->wq,
    139				   p9_xen_write_todo(ring, size)) != 0)
    140		;
    141
    142	spin_lock_irqsave(&ring->lock, flags);
    143	cons = ring->intf->out_cons;
    144	prod = ring->intf->out_prod;
    145	virt_mb();
    146
    147	if (XEN_9PFS_RING_SIZE(ring) -
    148	    xen_9pfs_queued(prod, cons, XEN_9PFS_RING_SIZE(ring)) < size) {
    149		spin_unlock_irqrestore(&ring->lock, flags);
    150		goto again;
    151	}
    152
    153	masked_prod = xen_9pfs_mask(prod, XEN_9PFS_RING_SIZE(ring));
    154	masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE(ring));
    155
    156	xen_9pfs_write_packet(ring->data.out, p9_req->tc.sdata, size,
    157			      &masked_prod, masked_cons,
    158			      XEN_9PFS_RING_SIZE(ring));
    159
    160	p9_req->status = REQ_STATUS_SENT;
    161	virt_wmb();			/* write ring before updating pointer */
    162	prod += size;
    163	ring->intf->out_prod = prod;
    164	spin_unlock_irqrestore(&ring->lock, flags);
    165	notify_remote_via_irq(ring->irq);
    166	p9_req_put(p9_req);
    167
    168	return 0;
    169}
    170
    171static void p9_xen_response(struct work_struct *work)
    172{
    173	struct xen_9pfs_front_priv *priv;
    174	struct xen_9pfs_dataring *ring;
    175	RING_IDX cons, prod, masked_cons, masked_prod;
    176	struct xen_9pfs_header h;
    177	struct p9_req_t *req;
    178	int status;
    179
    180	ring = container_of(work, struct xen_9pfs_dataring, work);
    181	priv = ring->priv;
    182
    183	while (1) {
    184		cons = ring->intf->in_cons;
    185		prod = ring->intf->in_prod;
    186		virt_rmb();
    187
    188		if (xen_9pfs_queued(prod, cons, XEN_9PFS_RING_SIZE(ring)) <
    189		    sizeof(h)) {
    190			notify_remote_via_irq(ring->irq);
    191			return;
    192		}
    193
    194		masked_prod = xen_9pfs_mask(prod, XEN_9PFS_RING_SIZE(ring));
    195		masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE(ring));
    196
    197		/* First, read just the header */
    198		xen_9pfs_read_packet(&h, ring->data.in, sizeof(h),
    199				     masked_prod, &masked_cons,
    200				     XEN_9PFS_RING_SIZE(ring));
    201
    202		req = p9_tag_lookup(priv->client, h.tag);
    203		if (!req || req->status != REQ_STATUS_SENT) {
    204			dev_warn(&priv->dev->dev, "Wrong req tag=%x\n", h.tag);
    205			cons += h.size;
    206			virt_mb();
    207			ring->intf->in_cons = cons;
    208			continue;
    209		}
    210
    211		memcpy(&req->rc, &h, sizeof(h));
    212		req->rc.offset = 0;
    213
    214		masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE(ring));
    215		/* Then, read the whole packet (including the header) */
    216		xen_9pfs_read_packet(req->rc.sdata, ring->data.in, h.size,
    217				     masked_prod, &masked_cons,
    218				     XEN_9PFS_RING_SIZE(ring));
    219
    220		virt_mb();
    221		cons += h.size;
    222		ring->intf->in_cons = cons;
    223
    224		status = (req->status != REQ_STATUS_ERROR) ?
    225			REQ_STATUS_RCVD : REQ_STATUS_ERROR;
    226
    227		p9_client_cb(priv->client, req, status);
    228	}
    229}
    230
    231static irqreturn_t xen_9pfs_front_event_handler(int irq, void *r)
    232{
    233	struct xen_9pfs_dataring *ring = r;
    234
    235	if (!ring || !ring->priv->client) {
    236		/* ignore spurious interrupt */
    237		return IRQ_HANDLED;
    238	}
    239
    240	wake_up_interruptible(&ring->wq);
    241	schedule_work(&ring->work);
    242
    243	return IRQ_HANDLED;
    244}
    245
    246static struct p9_trans_module p9_xen_trans = {
    247	.name = "xen",
    248	.maxsize = 1 << (XEN_9PFS_RING_ORDER + XEN_PAGE_SHIFT - 2),
    249	.def = 1,
    250	.create = p9_xen_create,
    251	.close = p9_xen_close,
    252	.request = p9_xen_request,
    253	.cancel = p9_xen_cancel,
    254	.owner = THIS_MODULE,
    255};
    256
    257static const struct xenbus_device_id xen_9pfs_front_ids[] = {
    258	{ "9pfs" },
    259	{ "" }
    260};
    261
    262static void xen_9pfs_front_free(struct xen_9pfs_front_priv *priv)
    263{
    264	int i, j;
    265
    266	write_lock(&xen_9pfs_lock);
    267	list_del(&priv->list);
    268	write_unlock(&xen_9pfs_lock);
    269
    270	for (i = 0; i < priv->num_rings; i++) {
    271		if (!priv->rings[i].intf)
    272			break;
    273		if (priv->rings[i].irq > 0)
    274			unbind_from_irqhandler(priv->rings[i].irq, priv->dev);
    275		if (priv->rings[i].data.in) {
    276			for (j = 0;
    277			     j < (1 << priv->rings[i].intf->ring_order);
    278			     j++) {
    279				grant_ref_t ref;
    280
    281				ref = priv->rings[i].intf->ref[j];
    282				gnttab_end_foreign_access(ref, NULL);
    283			}
    284			free_pages_exact(priv->rings[i].data.in,
    285				   1UL << (priv->rings[i].intf->ring_order +
    286					   XEN_PAGE_SHIFT));
    287		}
    288		gnttab_end_foreign_access(priv->rings[i].ref, NULL);
    289		free_page((unsigned long)priv->rings[i].intf);
    290	}
    291	kfree(priv->rings);
    292	kfree(priv->tag);
    293	kfree(priv);
    294}
    295
    296static int xen_9pfs_front_remove(struct xenbus_device *dev)
    297{
    298	struct xen_9pfs_front_priv *priv = dev_get_drvdata(&dev->dev);
    299
    300	dev_set_drvdata(&dev->dev, NULL);
    301	xen_9pfs_front_free(priv);
    302	return 0;
    303}
    304
    305static int xen_9pfs_front_alloc_dataring(struct xenbus_device *dev,
    306					 struct xen_9pfs_dataring *ring,
    307					 unsigned int order)
    308{
    309	int i = 0;
    310	int ret = -ENOMEM;
    311	void *bytes = NULL;
    312
    313	init_waitqueue_head(&ring->wq);
    314	spin_lock_init(&ring->lock);
    315	INIT_WORK(&ring->work, p9_xen_response);
    316
    317	ring->intf = (struct xen_9pfs_data_intf *)get_zeroed_page(GFP_KERNEL);
    318	if (!ring->intf)
    319		return ret;
    320	ret = gnttab_grant_foreign_access(dev->otherend_id,
    321					  virt_to_gfn(ring->intf), 0);
    322	if (ret < 0)
    323		goto out;
    324	ring->ref = ret;
    325	bytes = alloc_pages_exact(1UL << (order + XEN_PAGE_SHIFT),
    326				  GFP_KERNEL | __GFP_ZERO);
    327	if (!bytes) {
    328		ret = -ENOMEM;
    329		goto out;
    330	}
    331	for (; i < (1 << order); i++) {
    332		ret = gnttab_grant_foreign_access(
    333				dev->otherend_id, virt_to_gfn(bytes) + i, 0);
    334		if (ret < 0)
    335			goto out;
    336		ring->intf->ref[i] = ret;
    337	}
    338	ring->intf->ring_order = order;
    339	ring->data.in = bytes;
    340	ring->data.out = bytes + XEN_FLEX_RING_SIZE(order);
    341
    342	ret = xenbus_alloc_evtchn(dev, &ring->evtchn);
    343	if (ret)
    344		goto out;
    345	ring->irq = bind_evtchn_to_irqhandler(ring->evtchn,
    346					      xen_9pfs_front_event_handler,
    347					      0, "xen_9pfs-frontend", ring);
    348	if (ring->irq >= 0)
    349		return 0;
    350
    351	xenbus_free_evtchn(dev, ring->evtchn);
    352	ret = ring->irq;
    353out:
    354	if (bytes) {
    355		for (i--; i >= 0; i--)
    356			gnttab_end_foreign_access(ring->intf->ref[i], NULL);
    357		free_pages_exact(bytes, 1UL << (order + XEN_PAGE_SHIFT));
    358	}
    359	gnttab_end_foreign_access(ring->ref, NULL);
    360	free_page((unsigned long)ring->intf);
    361	return ret;
    362}
    363
    364static int xen_9pfs_front_probe(struct xenbus_device *dev,
    365				const struct xenbus_device_id *id)
    366{
    367	int ret, i;
    368	struct xenbus_transaction xbt;
    369	struct xen_9pfs_front_priv *priv = NULL;
    370	char *versions;
    371	unsigned int max_rings, max_ring_order, len = 0;
    372
    373	versions = xenbus_read(XBT_NIL, dev->otherend, "versions", &len);
    374	if (IS_ERR(versions))
    375		return PTR_ERR(versions);
    376	if (strcmp(versions, "1")) {
    377		kfree(versions);
    378		return -EINVAL;
    379	}
    380	kfree(versions);
    381	max_rings = xenbus_read_unsigned(dev->otherend, "max-rings", 0);
    382	if (max_rings < XEN_9PFS_NUM_RINGS)
    383		return -EINVAL;
    384	max_ring_order = xenbus_read_unsigned(dev->otherend,
    385					      "max-ring-page-order", 0);
    386	if (max_ring_order > XEN_9PFS_RING_ORDER)
    387		max_ring_order = XEN_9PFS_RING_ORDER;
    388	if (p9_xen_trans.maxsize > XEN_FLEX_RING_SIZE(max_ring_order))
    389		p9_xen_trans.maxsize = XEN_FLEX_RING_SIZE(max_ring_order) / 2;
    390
    391	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    392	if (!priv)
    393		return -ENOMEM;
    394
    395	priv->dev = dev;
    396	priv->num_rings = XEN_9PFS_NUM_RINGS;
    397	priv->rings = kcalloc(priv->num_rings, sizeof(*priv->rings),
    398			      GFP_KERNEL);
    399	if (!priv->rings) {
    400		kfree(priv);
    401		return -ENOMEM;
    402	}
    403
    404	for (i = 0; i < priv->num_rings; i++) {
    405		priv->rings[i].priv = priv;
    406		ret = xen_9pfs_front_alloc_dataring(dev, &priv->rings[i],
    407						    max_ring_order);
    408		if (ret < 0)
    409			goto error;
    410	}
    411
    412 again:
    413	ret = xenbus_transaction_start(&xbt);
    414	if (ret) {
    415		xenbus_dev_fatal(dev, ret, "starting transaction");
    416		goto error;
    417	}
    418	ret = xenbus_printf(xbt, dev->nodename, "version", "%u", 1);
    419	if (ret)
    420		goto error_xenbus;
    421	ret = xenbus_printf(xbt, dev->nodename, "num-rings", "%u",
    422			    priv->num_rings);
    423	if (ret)
    424		goto error_xenbus;
    425	for (i = 0; i < priv->num_rings; i++) {
    426		char str[16];
    427
    428		BUILD_BUG_ON(XEN_9PFS_NUM_RINGS > 9);
    429		sprintf(str, "ring-ref%d", i);
    430		ret = xenbus_printf(xbt, dev->nodename, str, "%d",
    431				    priv->rings[i].ref);
    432		if (ret)
    433			goto error_xenbus;
    434
    435		sprintf(str, "event-channel-%d", i);
    436		ret = xenbus_printf(xbt, dev->nodename, str, "%u",
    437				    priv->rings[i].evtchn);
    438		if (ret)
    439			goto error_xenbus;
    440	}
    441	priv->tag = xenbus_read(xbt, dev->nodename, "tag", NULL);
    442	if (IS_ERR(priv->tag)) {
    443		ret = PTR_ERR(priv->tag);
    444		goto error_xenbus;
    445	}
    446	ret = xenbus_transaction_end(xbt, 0);
    447	if (ret) {
    448		if (ret == -EAGAIN)
    449			goto again;
    450		xenbus_dev_fatal(dev, ret, "completing transaction");
    451		goto error;
    452	}
    453
    454	write_lock(&xen_9pfs_lock);
    455	list_add_tail(&priv->list, &xen_9pfs_devs);
    456	write_unlock(&xen_9pfs_lock);
    457	dev_set_drvdata(&dev->dev, priv);
    458	xenbus_switch_state(dev, XenbusStateInitialised);
    459
    460	return 0;
    461
    462 error_xenbus:
    463	xenbus_transaction_end(xbt, 1);
    464	xenbus_dev_fatal(dev, ret, "writing xenstore");
    465 error:
    466	dev_set_drvdata(&dev->dev, NULL);
    467	xen_9pfs_front_free(priv);
    468	return ret;
    469}
    470
    471static int xen_9pfs_front_resume(struct xenbus_device *dev)
    472{
    473	dev_warn(&dev->dev, "suspend/resume unsupported\n");
    474	return 0;
    475}
    476
    477static void xen_9pfs_front_changed(struct xenbus_device *dev,
    478				   enum xenbus_state backend_state)
    479{
    480	switch (backend_state) {
    481	case XenbusStateReconfiguring:
    482	case XenbusStateReconfigured:
    483	case XenbusStateInitialising:
    484	case XenbusStateInitialised:
    485	case XenbusStateUnknown:
    486		break;
    487
    488	case XenbusStateInitWait:
    489		break;
    490
    491	case XenbusStateConnected:
    492		xenbus_switch_state(dev, XenbusStateConnected);
    493		break;
    494
    495	case XenbusStateClosed:
    496		if (dev->state == XenbusStateClosed)
    497			break;
    498		fallthrough;	/* Missed the backend's CLOSING state */
    499	case XenbusStateClosing:
    500		xenbus_frontend_closed(dev);
    501		break;
    502	}
    503}
    504
    505static struct xenbus_driver xen_9pfs_front_driver = {
    506	.ids = xen_9pfs_front_ids,
    507	.probe = xen_9pfs_front_probe,
    508	.remove = xen_9pfs_front_remove,
    509	.resume = xen_9pfs_front_resume,
    510	.otherend_changed = xen_9pfs_front_changed,
    511};
    512
    513static int p9_trans_xen_init(void)
    514{
    515	int rc;
    516
    517	if (!xen_domain())
    518		return -ENODEV;
    519
    520	pr_info("Initialising Xen transport for 9pfs\n");
    521
    522	v9fs_register_trans(&p9_xen_trans);
    523	rc = xenbus_register_frontend(&xen_9pfs_front_driver);
    524	if (rc)
    525		v9fs_unregister_trans(&p9_xen_trans);
    526
    527	return rc;
    528}
    529module_init(p9_trans_xen_init);
    530MODULE_ALIAS_9P("xen");
    531
    532static void p9_trans_xen_exit(void)
    533{
    534	v9fs_unregister_trans(&p9_xen_trans);
    535	return xenbus_unregister_driver(&xen_9pfs_front_driver);
    536}
    537module_exit(p9_trans_xen_exit);
    538
    539MODULE_ALIAS("xen:9pfs");
    540MODULE_AUTHOR("Stefano Stabellini <stefano@aporeto.com>");
    541MODULE_DESCRIPTION("Xen Transport for 9P");
    542MODULE_LICENSE("GPL");