blob: 06bd95d4d552173550d3096be8f28e9553211f20 [file] [log] [blame]
Stefano Stabellini72e59c32017-07-05 13:08:39 -07001/*
2 * (c) 2017 Stefano Stabellini <stefano@aporeto.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
Stefano Stabellinifb029872017-07-06 11:01:00 -070015#include <linux/inet.h>
Stefano Stabellini72e59c32017-07-05 13:08:39 -070016#include <linux/kthread.h>
17#include <linux/list.h>
18#include <linux/radix-tree.h>
19#include <linux/module.h>
20#include <linux/semaphore.h>
21#include <linux/wait.h>
Stefano Stabellinifb029872017-07-06 11:01:00 -070022#include <net/sock.h>
23#include <net/inet_common.h>
24#include <net/inet_connection_sock.h>
25#include <net/request_sock.h>
Stefano Stabellini72e59c32017-07-05 13:08:39 -070026
27#include <xen/events.h>
28#include <xen/grant_table.h>
29#include <xen/xen.h>
30#include <xen/xenbus.h>
31#include <xen/interface/io/pvcalls.h>
32
Stefano Stabellini0a9c75c2017-07-06 10:59:17 -070033#define PVCALLS_VERSIONS "1"
34#define MAX_RING_ORDER XENBUS_MAX_RING_GRANT_ORDER
35
Stefano Stabellini9be07332017-07-05 13:08:48 -070036struct pvcalls_back_global {
37 struct list_head frontends;
38 struct semaphore frontends_lock;
39} pvcalls_back_global;
40
Stefano Stabellinid0e4d562017-07-06 10:59:29 -070041/*
42 * Per-frontend data structure. It contains pointers to the command
43 * ring, its event channel, a list of active sockets and a tree of
44 * passive sockets.
45 */
46struct pvcalls_fedata {
47 struct list_head list;
48 struct xenbus_device *dev;
49 struct xen_pvcalls_sring *sring;
50 struct xen_pvcalls_back_ring ring;
51 int irq;
52 struct list_head socket_mappings;
53 struct radix_tree_root socketpass_mappings;
54 struct semaphore socket_lock;
55};
56
Stefano Stabellini5db4d282017-07-06 11:01:06 -070057struct pvcalls_ioworker {
58 struct work_struct register_work;
59 struct workqueue_struct *wq;
60};
61
62struct sock_mapping {
63 struct list_head list;
64 struct pvcalls_fedata *fedata;
Stefano Stabellini6f474e72017-07-06 11:01:07 -070065 struct sockpass_mapping *sockpass;
Stefano Stabellini5db4d282017-07-06 11:01:06 -070066 struct socket *sock;
67 uint64_t id;
68 grant_ref_t ref;
69 struct pvcalls_data_intf *ring;
70 void *bytes;
71 struct pvcalls_data data;
72 uint32_t ring_order;
73 int irq;
74 atomic_t read;
75 atomic_t write;
76 atomic_t io;
77 atomic_t release;
78 void (*saved_data_ready)(struct sock *sk);
79 struct pvcalls_ioworker ioworker;
80};
81
Stefano Stabellini331a63e2017-07-06 11:01:06 -070082struct sockpass_mapping {
83 struct list_head list;
84 struct pvcalls_fedata *fedata;
85 struct socket *sock;
86 uint64_t id;
87 struct xen_pvcalls_request reqcopy;
88 spinlock_t copy_lock;
89 struct workqueue_struct *wq;
90 struct work_struct register_work;
91 void (*saved_data_ready)(struct sock *sk);
92};
93
Stefano Stabellini5db4d282017-07-06 11:01:06 -070094static irqreturn_t pvcalls_back_conn_event(int irq, void *sock_map);
95static int pvcalls_back_release_active(struct xenbus_device *dev,
96 struct pvcalls_fedata *fedata,
97 struct sock_mapping *map);
98
99static void pvcalls_back_ioworker(struct work_struct *work)
100{
101}
102
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700103static int pvcalls_back_socket(struct xenbus_device *dev,
104 struct xen_pvcalls_request *req)
105{
Stefano Stabellinifb029872017-07-06 11:01:00 -0700106 struct pvcalls_fedata *fedata;
107 int ret;
108 struct xen_pvcalls_response *rsp;
109
110 fedata = dev_get_drvdata(&dev->dev);
111
112 if (req->u.socket.domain != AF_INET ||
113 req->u.socket.type != SOCK_STREAM ||
114 (req->u.socket.protocol != IPPROTO_IP &&
115 req->u.socket.protocol != AF_INET))
116 ret = -EAFNOSUPPORT;
117 else
118 ret = 0;
119
120 /* leave the actual socket allocation for later */
121
122 rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
123 rsp->req_id = req->req_id;
124 rsp->cmd = req->cmd;
125 rsp->u.socket.id = req->u.socket.id;
126 rsp->ret = ret;
127
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700128 return 0;
129}
130
Stefano Stabellini5db4d282017-07-06 11:01:06 -0700131static void pvcalls_sk_state_change(struct sock *sock)
132{
133 struct sock_mapping *map = sock->sk_user_data;
134 struct pvcalls_data_intf *intf;
135
136 if (map == NULL)
137 return;
138
139 intf = map->ring;
140 intf->in_error = -ENOTCONN;
141 notify_remote_via_irq(map->irq);
142}
143
144static void pvcalls_sk_data_ready(struct sock *sock)
145{
146}
147
148static struct sock_mapping *pvcalls_new_active_socket(
149 struct pvcalls_fedata *fedata,
150 uint64_t id,
151 grant_ref_t ref,
152 uint32_t evtchn,
153 struct socket *sock)
154{
155 int ret;
156 struct sock_mapping *map;
157 void *page;
158
159 map = kzalloc(sizeof(*map), GFP_KERNEL);
160 if (map == NULL)
161 return NULL;
162
163 map->fedata = fedata;
164 map->sock = sock;
165 map->id = id;
166 map->ref = ref;
167
168 ret = xenbus_map_ring_valloc(fedata->dev, &ref, 1, &page);
169 if (ret < 0)
170 goto out;
171 map->ring = page;
172 map->ring_order = map->ring->ring_order;
173 /* first read the order, then map the data ring */
174 virt_rmb();
175 if (map->ring_order > MAX_RING_ORDER) {
176 pr_warn("%s frontend requested ring_order %u, which is > MAX (%u)\n",
177 __func__, map->ring_order, MAX_RING_ORDER);
178 goto out;
179 }
180 ret = xenbus_map_ring_valloc(fedata->dev, map->ring->ref,
181 (1 << map->ring_order), &page);
182 if (ret < 0)
183 goto out;
184 map->bytes = page;
185
186 ret = bind_interdomain_evtchn_to_irqhandler(fedata->dev->otherend_id,
187 evtchn,
188 pvcalls_back_conn_event,
189 0,
190 "pvcalls-backend",
191 map);
192 if (ret < 0)
193 goto out;
194 map->irq = ret;
195
196 map->data.in = map->bytes;
197 map->data.out = map->bytes + XEN_FLEX_RING_SIZE(map->ring_order);
198
199 map->ioworker.wq = alloc_workqueue("pvcalls_io", WQ_UNBOUND, 1);
200 if (!map->ioworker.wq)
201 goto out;
202 atomic_set(&map->io, 1);
203 INIT_WORK(&map->ioworker.register_work, pvcalls_back_ioworker);
204
205 down(&fedata->socket_lock);
206 list_add_tail(&map->list, &fedata->socket_mappings);
207 up(&fedata->socket_lock);
208
209 write_lock_bh(&map->sock->sk->sk_callback_lock);
210 map->saved_data_ready = map->sock->sk->sk_data_ready;
211 map->sock->sk->sk_user_data = map;
212 map->sock->sk->sk_data_ready = pvcalls_sk_data_ready;
213 map->sock->sk->sk_state_change = pvcalls_sk_state_change;
214 write_unlock_bh(&map->sock->sk->sk_callback_lock);
215
216 return map;
217out:
218 down(&fedata->socket_lock);
219 list_del(&map->list);
220 pvcalls_back_release_active(fedata->dev, fedata, map);
221 up(&fedata->socket_lock);
222 return NULL;
223}
224
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700225static int pvcalls_back_connect(struct xenbus_device *dev,
226 struct xen_pvcalls_request *req)
227{
Stefano Stabellini5db4d282017-07-06 11:01:06 -0700228 struct pvcalls_fedata *fedata;
229 int ret = -EINVAL;
230 struct socket *sock;
231 struct sock_mapping *map;
232 struct xen_pvcalls_response *rsp;
233 struct sockaddr *sa = (struct sockaddr *)&req->u.connect.addr;
234
235 fedata = dev_get_drvdata(&dev->dev);
236
237 if (req->u.connect.len < sizeof(sa->sa_family) ||
238 req->u.connect.len > sizeof(req->u.connect.addr) ||
239 sa->sa_family != AF_INET)
240 goto out;
241
242 ret = sock_create(AF_INET, SOCK_STREAM, 0, &sock);
243 if (ret < 0)
244 goto out;
245 ret = inet_stream_connect(sock, sa, req->u.connect.len, 0);
246 if (ret < 0) {
247 sock_release(sock);
248 goto out;
249 }
250
251 map = pvcalls_new_active_socket(fedata,
252 req->u.connect.id,
253 req->u.connect.ref,
254 req->u.connect.evtchn,
255 sock);
256 if (!map) {
257 ret = -EFAULT;
258 sock_release(map->sock);
259 }
260
261out:
262 rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
263 rsp->req_id = req->req_id;
264 rsp->cmd = req->cmd;
265 rsp->u.connect.id = req->u.connect.id;
266 rsp->ret = ret;
267
268 return 0;
269}
270
271static int pvcalls_back_release_active(struct xenbus_device *dev,
272 struct pvcalls_fedata *fedata,
273 struct sock_mapping *map)
274{
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700275 return 0;
276}
277
278static int pvcalls_back_release(struct xenbus_device *dev,
279 struct xen_pvcalls_request *req)
280{
281 return 0;
282}
283
Stefano Stabellini331a63e2017-07-06 11:01:06 -0700284static void __pvcalls_back_accept(struct work_struct *work)
285{
Stefano Stabellini6f474e72017-07-06 11:01:07 -0700286 struct sockpass_mapping *mappass = container_of(
287 work, struct sockpass_mapping, register_work);
288 struct sock_mapping *map;
289 struct pvcalls_ioworker *iow;
290 struct pvcalls_fedata *fedata;
291 struct socket *sock;
292 struct xen_pvcalls_response *rsp;
293 struct xen_pvcalls_request *req;
294 int notify;
295 int ret = -EINVAL;
296 unsigned long flags;
297
298 fedata = mappass->fedata;
299 /*
300 * __pvcalls_back_accept can race against pvcalls_back_accept.
301 * We only need to check the value of "cmd" on read. It could be
302 * done atomically, but to simplify the code on the write side, we
303 * use a spinlock.
304 */
305 spin_lock_irqsave(&mappass->copy_lock, flags);
306 req = &mappass->reqcopy;
307 if (req->cmd != PVCALLS_ACCEPT) {
308 spin_unlock_irqrestore(&mappass->copy_lock, flags);
309 return;
310 }
311 spin_unlock_irqrestore(&mappass->copy_lock, flags);
312
313 sock = sock_alloc();
314 if (sock == NULL)
315 goto out_error;
316 sock->type = mappass->sock->type;
317 sock->ops = mappass->sock->ops;
318
319 ret = inet_accept(mappass->sock, sock, O_NONBLOCK, true);
320 if (ret == -EAGAIN) {
321 sock_release(sock);
322 goto out_error;
323 }
324
325 map = pvcalls_new_active_socket(fedata,
326 req->u.accept.id_new,
327 req->u.accept.ref,
328 req->u.accept.evtchn,
329 sock);
330 if (!map) {
331 ret = -EFAULT;
332 sock_release(sock);
333 goto out_error;
334 }
335
336 map->sockpass = mappass;
337 iow = &map->ioworker;
338 atomic_inc(&map->read);
339 atomic_inc(&map->io);
340 queue_work(iow->wq, &iow->register_work);
341
342out_error:
343 rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
344 rsp->req_id = req->req_id;
345 rsp->cmd = req->cmd;
346 rsp->u.accept.id = req->u.accept.id;
347 rsp->ret = ret;
348 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&fedata->ring, notify);
349 if (notify)
350 notify_remote_via_irq(fedata->irq);
351
352 mappass->reqcopy.cmd = 0;
Stefano Stabellini331a63e2017-07-06 11:01:06 -0700353}
354
355static void pvcalls_pass_sk_data_ready(struct sock *sock)
356{
Stefano Stabellini6f474e72017-07-06 11:01:07 -0700357 struct sockpass_mapping *mappass = sock->sk_user_data;
Stefano Stabellini3cf33a5872017-07-06 11:01:07 -0700358 struct pvcalls_fedata *fedata;
359 struct xen_pvcalls_response *rsp;
360 unsigned long flags;
361 int notify;
Stefano Stabellini6f474e72017-07-06 11:01:07 -0700362
363 if (mappass == NULL)
364 return;
365
Stefano Stabellini3cf33a5872017-07-06 11:01:07 -0700366 fedata = mappass->fedata;
367 spin_lock_irqsave(&mappass->copy_lock, flags);
368 if (mappass->reqcopy.cmd == PVCALLS_POLL) {
369 rsp = RING_GET_RESPONSE(&fedata->ring,
370 fedata->ring.rsp_prod_pvt++);
371 rsp->req_id = mappass->reqcopy.req_id;
372 rsp->u.poll.id = mappass->reqcopy.u.poll.id;
373 rsp->cmd = mappass->reqcopy.cmd;
374 rsp->ret = 0;
375
376 mappass->reqcopy.cmd = 0;
377 spin_unlock_irqrestore(&mappass->copy_lock, flags);
378
379 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&fedata->ring, notify);
380 if (notify)
381 notify_remote_via_irq(mappass->fedata->irq);
382 } else {
383 spin_unlock_irqrestore(&mappass->copy_lock, flags);
384 queue_work(mappass->wq, &mappass->register_work);
385 }
Stefano Stabellini331a63e2017-07-06 11:01:06 -0700386}
387
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700388static int pvcalls_back_bind(struct xenbus_device *dev,
389 struct xen_pvcalls_request *req)
390{
Stefano Stabellini331a63e2017-07-06 11:01:06 -0700391 struct pvcalls_fedata *fedata;
392 int ret;
393 struct sockpass_mapping *map;
394 struct xen_pvcalls_response *rsp;
395
396 fedata = dev_get_drvdata(&dev->dev);
397
398 map = kzalloc(sizeof(*map), GFP_KERNEL);
399 if (map == NULL) {
400 ret = -ENOMEM;
401 goto out;
402 }
403
404 INIT_WORK(&map->register_work, __pvcalls_back_accept);
405 spin_lock_init(&map->copy_lock);
406 map->wq = alloc_workqueue("pvcalls_wq", WQ_UNBOUND, 1);
407 if (!map->wq) {
408 ret = -ENOMEM;
409 goto out;
410 }
411
412 ret = sock_create(AF_INET, SOCK_STREAM, 0, &map->sock);
413 if (ret < 0)
414 goto out;
415
416 ret = inet_bind(map->sock, (struct sockaddr *)&req->u.bind.addr,
417 req->u.bind.len);
418 if (ret < 0)
419 goto out;
420
421 map->fedata = fedata;
422 map->id = req->u.bind.id;
423
424 down(&fedata->socket_lock);
425 ret = radix_tree_insert(&fedata->socketpass_mappings, map->id,
426 map);
427 up(&fedata->socket_lock);
428 if (ret)
429 goto out;
430
431 write_lock_bh(&map->sock->sk->sk_callback_lock);
432 map->saved_data_ready = map->sock->sk->sk_data_ready;
433 map->sock->sk->sk_user_data = map;
434 map->sock->sk->sk_data_ready = pvcalls_pass_sk_data_ready;
435 write_unlock_bh(&map->sock->sk->sk_callback_lock);
436
437out:
438 if (ret) {
439 if (map && map->sock)
440 sock_release(map->sock);
441 if (map && map->wq)
442 destroy_workqueue(map->wq);
443 kfree(map);
444 }
445 rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
446 rsp->req_id = req->req_id;
447 rsp->cmd = req->cmd;
448 rsp->u.bind.id = req->u.bind.id;
449 rsp->ret = ret;
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700450 return 0;
451}
452
453static int pvcalls_back_listen(struct xenbus_device *dev,
454 struct xen_pvcalls_request *req)
455{
Stefano Stabellini8ce3f762017-07-06 11:01:06 -0700456 struct pvcalls_fedata *fedata;
457 int ret = -EINVAL;
458 struct sockpass_mapping *map;
459 struct xen_pvcalls_response *rsp;
460
461 fedata = dev_get_drvdata(&dev->dev);
462
463 down(&fedata->socket_lock);
464 map = radix_tree_lookup(&fedata->socketpass_mappings, req->u.listen.id);
465 up(&fedata->socket_lock);
466 if (map == NULL)
467 goto out;
468
469 ret = inet_listen(map->sock, req->u.listen.backlog);
470
471out:
472 rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
473 rsp->req_id = req->req_id;
474 rsp->cmd = req->cmd;
475 rsp->u.listen.id = req->u.listen.id;
476 rsp->ret = ret;
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700477 return 0;
478}
479
480static int pvcalls_back_accept(struct xenbus_device *dev,
481 struct xen_pvcalls_request *req)
482{
Stefano Stabellini6f474e72017-07-06 11:01:07 -0700483 struct pvcalls_fedata *fedata;
484 struct sockpass_mapping *mappass;
485 int ret = -EINVAL;
486 struct xen_pvcalls_response *rsp;
487 unsigned long flags;
488
489 fedata = dev_get_drvdata(&dev->dev);
490
491 down(&fedata->socket_lock);
492 mappass = radix_tree_lookup(&fedata->socketpass_mappings,
493 req->u.accept.id);
494 up(&fedata->socket_lock);
495 if (mappass == NULL)
496 goto out_error;
497
498 /*
499 * Limitation of the current implementation: only support one
500 * concurrent accept or poll call on one socket.
501 */
502 spin_lock_irqsave(&mappass->copy_lock, flags);
503 if (mappass->reqcopy.cmd != 0) {
504 spin_unlock_irqrestore(&mappass->copy_lock, flags);
505 ret = -EINTR;
506 goto out_error;
507 }
508
509 mappass->reqcopy = *req;
510 spin_unlock_irqrestore(&mappass->copy_lock, flags);
511 queue_work(mappass->wq, &mappass->register_work);
512
513 /* Tell the caller we don't need to send back a notification yet */
514 return -1;
515
516out_error:
517 rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
518 rsp->req_id = req->req_id;
519 rsp->cmd = req->cmd;
520 rsp->u.accept.id = req->u.accept.id;
521 rsp->ret = ret;
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700522 return 0;
523}
524
525static int pvcalls_back_poll(struct xenbus_device *dev,
526 struct xen_pvcalls_request *req)
527{
Stefano Stabellini3cf33a5872017-07-06 11:01:07 -0700528 struct pvcalls_fedata *fedata;
529 struct sockpass_mapping *mappass;
530 struct xen_pvcalls_response *rsp;
531 struct inet_connection_sock *icsk;
532 struct request_sock_queue *queue;
533 unsigned long flags;
534 int ret;
535 bool data;
536
537 fedata = dev_get_drvdata(&dev->dev);
538
539 down(&fedata->socket_lock);
540 mappass = radix_tree_lookup(&fedata->socketpass_mappings,
541 req->u.poll.id);
542 up(&fedata->socket_lock);
543 if (mappass == NULL)
544 return -EINVAL;
545
546 /*
547 * Limitation of the current implementation: only support one
548 * concurrent accept or poll call on one socket.
549 */
550 spin_lock_irqsave(&mappass->copy_lock, flags);
551 if (mappass->reqcopy.cmd != 0) {
552 ret = -EINTR;
553 goto out;
554 }
555
556 mappass->reqcopy = *req;
557 icsk = inet_csk(mappass->sock->sk);
558 queue = &icsk->icsk_accept_queue;
559 data = queue->rskq_accept_head != NULL;
560 if (data) {
561 mappass->reqcopy.cmd = 0;
562 ret = 0;
563 goto out;
564 }
565 spin_unlock_irqrestore(&mappass->copy_lock, flags);
566
567 /* Tell the caller we don't need to send back a notification yet */
568 return -1;
569
570out:
571 spin_unlock_irqrestore(&mappass->copy_lock, flags);
572
573 rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
574 rsp->req_id = req->req_id;
575 rsp->cmd = req->cmd;
576 rsp->u.poll.id = req->u.poll.id;
577 rsp->ret = ret;
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700578 return 0;
579}
580
581static int pvcalls_back_handle_cmd(struct xenbus_device *dev,
582 struct xen_pvcalls_request *req)
583{
584 int ret = 0;
585
586 switch (req->cmd) {
587 case PVCALLS_SOCKET:
588 ret = pvcalls_back_socket(dev, req);
589 break;
590 case PVCALLS_CONNECT:
591 ret = pvcalls_back_connect(dev, req);
592 break;
593 case PVCALLS_RELEASE:
594 ret = pvcalls_back_release(dev, req);
595 break;
596 case PVCALLS_BIND:
597 ret = pvcalls_back_bind(dev, req);
598 break;
599 case PVCALLS_LISTEN:
600 ret = pvcalls_back_listen(dev, req);
601 break;
602 case PVCALLS_ACCEPT:
603 ret = pvcalls_back_accept(dev, req);
604 break;
605 case PVCALLS_POLL:
606 ret = pvcalls_back_poll(dev, req);
607 break;
608 default:
609 {
610 struct pvcalls_fedata *fedata;
611 struct xen_pvcalls_response *rsp;
612
613 fedata = dev_get_drvdata(&dev->dev);
614 rsp = RING_GET_RESPONSE(
615 &fedata->ring, fedata->ring.rsp_prod_pvt++);
616 rsp->req_id = req->req_id;
617 rsp->cmd = req->cmd;
618 rsp->ret = -ENOTSUPP;
619 break;
620 }
621 }
622 return ret;
623}
624
625static void pvcalls_back_work(struct pvcalls_fedata *fedata)
626{
627 int notify, notify_all = 0, more = 1;
628 struct xen_pvcalls_request req;
629 struct xenbus_device *dev = fedata->dev;
630
631 while (more) {
632 while (RING_HAS_UNCONSUMED_REQUESTS(&fedata->ring)) {
633 RING_COPY_REQUEST(&fedata->ring,
634 fedata->ring.req_cons++,
635 &req);
636
637 if (!pvcalls_back_handle_cmd(dev, &req)) {
638 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(
639 &fedata->ring, notify);
640 notify_all += notify;
641 }
642 }
643
644 if (notify_all) {
645 notify_remote_via_irq(fedata->irq);
646 notify_all = 0;
647 }
648
649 RING_FINAL_CHECK_FOR_REQUESTS(&fedata->ring, more);
650 }
651}
652
Stefano Stabellinid0e4d562017-07-06 10:59:29 -0700653static irqreturn_t pvcalls_back_event(int irq, void *dev_id)
654{
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700655 struct xenbus_device *dev = dev_id;
656 struct pvcalls_fedata *fedata = NULL;
657
658 if (dev == NULL)
659 return IRQ_HANDLED;
660
661 fedata = dev_get_drvdata(&dev->dev);
662 if (fedata == NULL)
663 return IRQ_HANDLED;
664
665 pvcalls_back_work(fedata);
Stefano Stabellinid0e4d562017-07-06 10:59:29 -0700666 return IRQ_HANDLED;
667}
668
Stefano Stabellini5db4d282017-07-06 11:01:06 -0700669static irqreturn_t pvcalls_back_conn_event(int irq, void *sock_map)
670{
671 return IRQ_HANDLED;
672}
673
Stefano Stabellini0a9c75c2017-07-06 10:59:17 -0700674static int backend_connect(struct xenbus_device *dev)
675{
Stefano Stabellinid0e4d562017-07-06 10:59:29 -0700676 int err, evtchn;
677 grant_ref_t ring_ref;
678 struct pvcalls_fedata *fedata = NULL;
679
680 fedata = kzalloc(sizeof(struct pvcalls_fedata), GFP_KERNEL);
681 if (!fedata)
682 return -ENOMEM;
683
684 fedata->irq = -1;
685 err = xenbus_scanf(XBT_NIL, dev->otherend, "port", "%u",
686 &evtchn);
687 if (err != 1) {
688 err = -EINVAL;
689 xenbus_dev_fatal(dev, err, "reading %s/event-channel",
690 dev->otherend);
691 goto error;
692 }
693
694 err = xenbus_scanf(XBT_NIL, dev->otherend, "ring-ref", "%u", &ring_ref);
695 if (err != 1) {
696 err = -EINVAL;
697 xenbus_dev_fatal(dev, err, "reading %s/ring-ref",
698 dev->otherend);
699 goto error;
700 }
701
702 err = bind_interdomain_evtchn_to_irq(dev->otherend_id, evtchn);
703 if (err < 0)
704 goto error;
705 fedata->irq = err;
706
707 err = request_threaded_irq(fedata->irq, NULL, pvcalls_back_event,
708 IRQF_ONESHOT, "pvcalls-back", dev);
709 if (err < 0)
710 goto error;
711
712 err = xenbus_map_ring_valloc(dev, &ring_ref, 1,
713 (void **)&fedata->sring);
714 if (err < 0)
715 goto error;
716
717 BACK_RING_INIT(&fedata->ring, fedata->sring, XEN_PAGE_SIZE * 1);
718 fedata->dev = dev;
719
720 INIT_LIST_HEAD(&fedata->socket_mappings);
721 INIT_RADIX_TREE(&fedata->socketpass_mappings, GFP_KERNEL);
722 sema_init(&fedata->socket_lock, 1);
723 dev_set_drvdata(&dev->dev, fedata);
724
725 down(&pvcalls_back_global.frontends_lock);
726 list_add_tail(&fedata->list, &pvcalls_back_global.frontends);
727 up(&pvcalls_back_global.frontends_lock);
728
Stefano Stabellini0a9c75c2017-07-06 10:59:17 -0700729 return 0;
Stefano Stabellinid0e4d562017-07-06 10:59:29 -0700730
731 error:
732 if (fedata->irq >= 0)
733 unbind_from_irqhandler(fedata->irq, dev);
734 if (fedata->sring != NULL)
735 xenbus_unmap_ring_vfree(dev, fedata->sring);
736 kfree(fedata);
737 return err;
Stefano Stabellini0a9c75c2017-07-06 10:59:17 -0700738}
739
740static int backend_disconnect(struct xenbus_device *dev)
741{
742 return 0;
743}
744
Stefano Stabellini72e59c32017-07-05 13:08:39 -0700745static int pvcalls_back_probe(struct xenbus_device *dev,
746 const struct xenbus_device_id *id)
747{
Stefano Stabellini0a9c75c2017-07-06 10:59:17 -0700748 int err, abort;
749 struct xenbus_transaction xbt;
750
751again:
752 abort = 1;
753
754 err = xenbus_transaction_start(&xbt);
755 if (err) {
756 pr_warn("%s cannot create xenstore transaction\n", __func__);
757 return err;
758 }
759
760 err = xenbus_printf(xbt, dev->nodename, "versions", "%s",
761 PVCALLS_VERSIONS);
762 if (err) {
763 pr_warn("%s write out 'versions' failed\n", __func__);
764 goto abort;
765 }
766
767 err = xenbus_printf(xbt, dev->nodename, "max-page-order", "%u",
768 MAX_RING_ORDER);
769 if (err) {
770 pr_warn("%s write out 'max-page-order' failed\n", __func__);
771 goto abort;
772 }
773
774 err = xenbus_printf(xbt, dev->nodename, "function-calls",
775 XENBUS_FUNCTIONS_CALLS);
776 if (err) {
777 pr_warn("%s write out 'function-calls' failed\n", __func__);
778 goto abort;
779 }
780
781 abort = 0;
782abort:
783 err = xenbus_transaction_end(xbt, abort);
784 if (err) {
785 if (err == -EAGAIN && !abort)
786 goto again;
787 pr_warn("%s cannot complete xenstore transaction\n", __func__);
788 return err;
789 }
790
791 if (abort)
792 return -EFAULT;
793
794 xenbus_switch_state(dev, XenbusStateInitWait);
795
Stefano Stabellini72e59c32017-07-05 13:08:39 -0700796 return 0;
797}
798
Stefano Stabellini0a9c75c2017-07-06 10:59:17 -0700799static void set_backend_state(struct xenbus_device *dev,
800 enum xenbus_state state)
801{
802 while (dev->state != state) {
803 switch (dev->state) {
804 case XenbusStateClosed:
805 switch (state) {
806 case XenbusStateInitWait:
807 case XenbusStateConnected:
808 xenbus_switch_state(dev, XenbusStateInitWait);
809 break;
810 case XenbusStateClosing:
811 xenbus_switch_state(dev, XenbusStateClosing);
812 break;
813 default:
814 __WARN();
815 }
816 break;
817 case XenbusStateInitWait:
818 case XenbusStateInitialised:
819 switch (state) {
820 case XenbusStateConnected:
821 backend_connect(dev);
822 xenbus_switch_state(dev, XenbusStateConnected);
823 break;
824 case XenbusStateClosing:
825 case XenbusStateClosed:
826 xenbus_switch_state(dev, XenbusStateClosing);
827 break;
828 default:
829 __WARN();
830 }
831 break;
832 case XenbusStateConnected:
833 switch (state) {
834 case XenbusStateInitWait:
835 case XenbusStateClosing:
836 case XenbusStateClosed:
837 down(&pvcalls_back_global.frontends_lock);
838 backend_disconnect(dev);
839 up(&pvcalls_back_global.frontends_lock);
840 xenbus_switch_state(dev, XenbusStateClosing);
841 break;
842 default:
843 __WARN();
844 }
845 break;
846 case XenbusStateClosing:
847 switch (state) {
848 case XenbusStateInitWait:
849 case XenbusStateConnected:
850 case XenbusStateClosed:
851 xenbus_switch_state(dev, XenbusStateClosed);
852 break;
853 default:
854 __WARN();
855 }
856 break;
857 default:
858 __WARN();
859 }
860 }
861}
862
Stefano Stabellini72e59c32017-07-05 13:08:39 -0700863static void pvcalls_back_changed(struct xenbus_device *dev,
864 enum xenbus_state frontend_state)
865{
Stefano Stabellini0a9c75c2017-07-06 10:59:17 -0700866 switch (frontend_state) {
867 case XenbusStateInitialising:
868 set_backend_state(dev, XenbusStateInitWait);
869 break;
870
871 case XenbusStateInitialised:
872 case XenbusStateConnected:
873 set_backend_state(dev, XenbusStateConnected);
874 break;
875
876 case XenbusStateClosing:
877 set_backend_state(dev, XenbusStateClosing);
878 break;
879
880 case XenbusStateClosed:
881 set_backend_state(dev, XenbusStateClosed);
882 if (xenbus_dev_is_online(dev))
883 break;
884 device_unregister(&dev->dev);
885 break;
886 case XenbusStateUnknown:
887 set_backend_state(dev, XenbusStateClosed);
888 device_unregister(&dev->dev);
889 break;
890
891 default:
892 xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
893 frontend_state);
894 break;
895 }
Stefano Stabellini72e59c32017-07-05 13:08:39 -0700896}
897
898static int pvcalls_back_remove(struct xenbus_device *dev)
899{
900 return 0;
901}
902
903static int pvcalls_back_uevent(struct xenbus_device *xdev,
904 struct kobj_uevent_env *env)
905{
906 return 0;
907}
908
909static const struct xenbus_device_id pvcalls_back_ids[] = {
910 { "pvcalls" },
911 { "" }
912};
913
914static struct xenbus_driver pvcalls_back_driver = {
915 .ids = pvcalls_back_ids,
916 .probe = pvcalls_back_probe,
917 .remove = pvcalls_back_remove,
918 .uevent = pvcalls_back_uevent,
919 .otherend_changed = pvcalls_back_changed,
920};
Stefano Stabellini9be07332017-07-05 13:08:48 -0700921
922static int __init pvcalls_back_init(void)
923{
924 int ret;
925
926 if (!xen_domain())
927 return -ENODEV;
928
929 ret = xenbus_register_backend(&pvcalls_back_driver);
930 if (ret < 0)
931 return ret;
932
933 sema_init(&pvcalls_back_global.frontends_lock, 1);
934 INIT_LIST_HEAD(&pvcalls_back_global.frontends);
935 return 0;
936}
937module_init(pvcalls_back_init);