blob: 7bdf9245cfaba0a77d98a4b671151af8c239eacb [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 Stabellinia51729c2017-07-06 11:01:07 -0700275 disable_irq(map->irq);
276 if (map->sock->sk != NULL) {
277 write_lock_bh(&map->sock->sk->sk_callback_lock);
278 map->sock->sk->sk_user_data = NULL;
279 map->sock->sk->sk_data_ready = map->saved_data_ready;
280 write_unlock_bh(&map->sock->sk->sk_callback_lock);
281 }
282
283 atomic_set(&map->release, 1);
284 flush_work(&map->ioworker.register_work);
285
286 xenbus_unmap_ring_vfree(dev, map->bytes);
287 xenbus_unmap_ring_vfree(dev, (void *)map->ring);
288 unbind_from_irqhandler(map->irq, map);
289
290 sock_release(map->sock);
291 kfree(map);
292
293 return 0;
294}
295
296static int pvcalls_back_release_passive(struct xenbus_device *dev,
297 struct pvcalls_fedata *fedata,
298 struct sockpass_mapping *mappass)
299{
300 if (mappass->sock->sk != NULL) {
301 write_lock_bh(&mappass->sock->sk->sk_callback_lock);
302 mappass->sock->sk->sk_user_data = NULL;
303 mappass->sock->sk->sk_data_ready = mappass->saved_data_ready;
304 write_unlock_bh(&mappass->sock->sk->sk_callback_lock);
305 }
306 sock_release(mappass->sock);
307 flush_workqueue(mappass->wq);
308 destroy_workqueue(mappass->wq);
309 kfree(mappass);
310
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700311 return 0;
312}
313
314static int pvcalls_back_release(struct xenbus_device *dev,
315 struct xen_pvcalls_request *req)
316{
Stefano Stabellinia51729c2017-07-06 11:01:07 -0700317 struct pvcalls_fedata *fedata;
318 struct sock_mapping *map, *n;
319 struct sockpass_mapping *mappass;
320 int ret = 0;
321 struct xen_pvcalls_response *rsp;
322
323 fedata = dev_get_drvdata(&dev->dev);
324
325 down(&fedata->socket_lock);
326 list_for_each_entry_safe(map, n, &fedata->socket_mappings, list) {
327 if (map->id == req->u.release.id) {
328 list_del(&map->list);
329 up(&fedata->socket_lock);
330 ret = pvcalls_back_release_active(dev, fedata, map);
331 goto out;
332 }
333 }
334 mappass = radix_tree_lookup(&fedata->socketpass_mappings,
335 req->u.release.id);
336 if (mappass != NULL) {
337 radix_tree_delete(&fedata->socketpass_mappings, mappass->id);
338 up(&fedata->socket_lock);
339 ret = pvcalls_back_release_passive(dev, fedata, mappass);
340 } else
341 up(&fedata->socket_lock);
342
343out:
344 rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
345 rsp->req_id = req->req_id;
346 rsp->u.release.id = req->u.release.id;
347 rsp->cmd = req->cmd;
348 rsp->ret = ret;
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700349 return 0;
350}
351
Stefano Stabellini331a63e2017-07-06 11:01:06 -0700352static void __pvcalls_back_accept(struct work_struct *work)
353{
Stefano Stabellini6f474e72017-07-06 11:01:07 -0700354 struct sockpass_mapping *mappass = container_of(
355 work, struct sockpass_mapping, register_work);
356 struct sock_mapping *map;
357 struct pvcalls_ioworker *iow;
358 struct pvcalls_fedata *fedata;
359 struct socket *sock;
360 struct xen_pvcalls_response *rsp;
361 struct xen_pvcalls_request *req;
362 int notify;
363 int ret = -EINVAL;
364 unsigned long flags;
365
366 fedata = mappass->fedata;
367 /*
368 * __pvcalls_back_accept can race against pvcalls_back_accept.
369 * We only need to check the value of "cmd" on read. It could be
370 * done atomically, but to simplify the code on the write side, we
371 * use a spinlock.
372 */
373 spin_lock_irqsave(&mappass->copy_lock, flags);
374 req = &mappass->reqcopy;
375 if (req->cmd != PVCALLS_ACCEPT) {
376 spin_unlock_irqrestore(&mappass->copy_lock, flags);
377 return;
378 }
379 spin_unlock_irqrestore(&mappass->copy_lock, flags);
380
381 sock = sock_alloc();
382 if (sock == NULL)
383 goto out_error;
384 sock->type = mappass->sock->type;
385 sock->ops = mappass->sock->ops;
386
387 ret = inet_accept(mappass->sock, sock, O_NONBLOCK, true);
388 if (ret == -EAGAIN) {
389 sock_release(sock);
390 goto out_error;
391 }
392
393 map = pvcalls_new_active_socket(fedata,
394 req->u.accept.id_new,
395 req->u.accept.ref,
396 req->u.accept.evtchn,
397 sock);
398 if (!map) {
399 ret = -EFAULT;
400 sock_release(sock);
401 goto out_error;
402 }
403
404 map->sockpass = mappass;
405 iow = &map->ioworker;
406 atomic_inc(&map->read);
407 atomic_inc(&map->io);
408 queue_work(iow->wq, &iow->register_work);
409
410out_error:
411 rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
412 rsp->req_id = req->req_id;
413 rsp->cmd = req->cmd;
414 rsp->u.accept.id = req->u.accept.id;
415 rsp->ret = ret;
416 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&fedata->ring, notify);
417 if (notify)
418 notify_remote_via_irq(fedata->irq);
419
420 mappass->reqcopy.cmd = 0;
Stefano Stabellini331a63e2017-07-06 11:01:06 -0700421}
422
423static void pvcalls_pass_sk_data_ready(struct sock *sock)
424{
Stefano Stabellini6f474e72017-07-06 11:01:07 -0700425 struct sockpass_mapping *mappass = sock->sk_user_data;
Stefano Stabellini3cf33a5872017-07-06 11:01:07 -0700426 struct pvcalls_fedata *fedata;
427 struct xen_pvcalls_response *rsp;
428 unsigned long flags;
429 int notify;
Stefano Stabellini6f474e72017-07-06 11:01:07 -0700430
431 if (mappass == NULL)
432 return;
433
Stefano Stabellini3cf33a5872017-07-06 11:01:07 -0700434 fedata = mappass->fedata;
435 spin_lock_irqsave(&mappass->copy_lock, flags);
436 if (mappass->reqcopy.cmd == PVCALLS_POLL) {
437 rsp = RING_GET_RESPONSE(&fedata->ring,
438 fedata->ring.rsp_prod_pvt++);
439 rsp->req_id = mappass->reqcopy.req_id;
440 rsp->u.poll.id = mappass->reqcopy.u.poll.id;
441 rsp->cmd = mappass->reqcopy.cmd;
442 rsp->ret = 0;
443
444 mappass->reqcopy.cmd = 0;
445 spin_unlock_irqrestore(&mappass->copy_lock, flags);
446
447 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&fedata->ring, notify);
448 if (notify)
449 notify_remote_via_irq(mappass->fedata->irq);
450 } else {
451 spin_unlock_irqrestore(&mappass->copy_lock, flags);
452 queue_work(mappass->wq, &mappass->register_work);
453 }
Stefano Stabellini331a63e2017-07-06 11:01:06 -0700454}
455
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700456static int pvcalls_back_bind(struct xenbus_device *dev,
457 struct xen_pvcalls_request *req)
458{
Stefano Stabellini331a63e2017-07-06 11:01:06 -0700459 struct pvcalls_fedata *fedata;
460 int ret;
461 struct sockpass_mapping *map;
462 struct xen_pvcalls_response *rsp;
463
464 fedata = dev_get_drvdata(&dev->dev);
465
466 map = kzalloc(sizeof(*map), GFP_KERNEL);
467 if (map == NULL) {
468 ret = -ENOMEM;
469 goto out;
470 }
471
472 INIT_WORK(&map->register_work, __pvcalls_back_accept);
473 spin_lock_init(&map->copy_lock);
474 map->wq = alloc_workqueue("pvcalls_wq", WQ_UNBOUND, 1);
475 if (!map->wq) {
476 ret = -ENOMEM;
477 goto out;
478 }
479
480 ret = sock_create(AF_INET, SOCK_STREAM, 0, &map->sock);
481 if (ret < 0)
482 goto out;
483
484 ret = inet_bind(map->sock, (struct sockaddr *)&req->u.bind.addr,
485 req->u.bind.len);
486 if (ret < 0)
487 goto out;
488
489 map->fedata = fedata;
490 map->id = req->u.bind.id;
491
492 down(&fedata->socket_lock);
493 ret = radix_tree_insert(&fedata->socketpass_mappings, map->id,
494 map);
495 up(&fedata->socket_lock);
496 if (ret)
497 goto out;
498
499 write_lock_bh(&map->sock->sk->sk_callback_lock);
500 map->saved_data_ready = map->sock->sk->sk_data_ready;
501 map->sock->sk->sk_user_data = map;
502 map->sock->sk->sk_data_ready = pvcalls_pass_sk_data_ready;
503 write_unlock_bh(&map->sock->sk->sk_callback_lock);
504
505out:
506 if (ret) {
507 if (map && map->sock)
508 sock_release(map->sock);
509 if (map && map->wq)
510 destroy_workqueue(map->wq);
511 kfree(map);
512 }
513 rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
514 rsp->req_id = req->req_id;
515 rsp->cmd = req->cmd;
516 rsp->u.bind.id = req->u.bind.id;
517 rsp->ret = ret;
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700518 return 0;
519}
520
521static int pvcalls_back_listen(struct xenbus_device *dev,
522 struct xen_pvcalls_request *req)
523{
Stefano Stabellini8ce3f762017-07-06 11:01:06 -0700524 struct pvcalls_fedata *fedata;
525 int ret = -EINVAL;
526 struct sockpass_mapping *map;
527 struct xen_pvcalls_response *rsp;
528
529 fedata = dev_get_drvdata(&dev->dev);
530
531 down(&fedata->socket_lock);
532 map = radix_tree_lookup(&fedata->socketpass_mappings, req->u.listen.id);
533 up(&fedata->socket_lock);
534 if (map == NULL)
535 goto out;
536
537 ret = inet_listen(map->sock, req->u.listen.backlog);
538
539out:
540 rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
541 rsp->req_id = req->req_id;
542 rsp->cmd = req->cmd;
543 rsp->u.listen.id = req->u.listen.id;
544 rsp->ret = ret;
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700545 return 0;
546}
547
548static int pvcalls_back_accept(struct xenbus_device *dev,
549 struct xen_pvcalls_request *req)
550{
Stefano Stabellini6f474e72017-07-06 11:01:07 -0700551 struct pvcalls_fedata *fedata;
552 struct sockpass_mapping *mappass;
553 int ret = -EINVAL;
554 struct xen_pvcalls_response *rsp;
555 unsigned long flags;
556
557 fedata = dev_get_drvdata(&dev->dev);
558
559 down(&fedata->socket_lock);
560 mappass = radix_tree_lookup(&fedata->socketpass_mappings,
561 req->u.accept.id);
562 up(&fedata->socket_lock);
563 if (mappass == NULL)
564 goto out_error;
565
566 /*
567 * Limitation of the current implementation: only support one
568 * concurrent accept or poll call on one socket.
569 */
570 spin_lock_irqsave(&mappass->copy_lock, flags);
571 if (mappass->reqcopy.cmd != 0) {
572 spin_unlock_irqrestore(&mappass->copy_lock, flags);
573 ret = -EINTR;
574 goto out_error;
575 }
576
577 mappass->reqcopy = *req;
578 spin_unlock_irqrestore(&mappass->copy_lock, flags);
579 queue_work(mappass->wq, &mappass->register_work);
580
581 /* Tell the caller we don't need to send back a notification yet */
582 return -1;
583
584out_error:
585 rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
586 rsp->req_id = req->req_id;
587 rsp->cmd = req->cmd;
588 rsp->u.accept.id = req->u.accept.id;
589 rsp->ret = ret;
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700590 return 0;
591}
592
593static int pvcalls_back_poll(struct xenbus_device *dev,
594 struct xen_pvcalls_request *req)
595{
Stefano Stabellini3cf33a5872017-07-06 11:01:07 -0700596 struct pvcalls_fedata *fedata;
597 struct sockpass_mapping *mappass;
598 struct xen_pvcalls_response *rsp;
599 struct inet_connection_sock *icsk;
600 struct request_sock_queue *queue;
601 unsigned long flags;
602 int ret;
603 bool data;
604
605 fedata = dev_get_drvdata(&dev->dev);
606
607 down(&fedata->socket_lock);
608 mappass = radix_tree_lookup(&fedata->socketpass_mappings,
609 req->u.poll.id);
610 up(&fedata->socket_lock);
611 if (mappass == NULL)
612 return -EINVAL;
613
614 /*
615 * Limitation of the current implementation: only support one
616 * concurrent accept or poll call on one socket.
617 */
618 spin_lock_irqsave(&mappass->copy_lock, flags);
619 if (mappass->reqcopy.cmd != 0) {
620 ret = -EINTR;
621 goto out;
622 }
623
624 mappass->reqcopy = *req;
625 icsk = inet_csk(mappass->sock->sk);
626 queue = &icsk->icsk_accept_queue;
627 data = queue->rskq_accept_head != NULL;
628 if (data) {
629 mappass->reqcopy.cmd = 0;
630 ret = 0;
631 goto out;
632 }
633 spin_unlock_irqrestore(&mappass->copy_lock, flags);
634
635 /* Tell the caller we don't need to send back a notification yet */
636 return -1;
637
638out:
639 spin_unlock_irqrestore(&mappass->copy_lock, flags);
640
641 rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
642 rsp->req_id = req->req_id;
643 rsp->cmd = req->cmd;
644 rsp->u.poll.id = req->u.poll.id;
645 rsp->ret = ret;
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700646 return 0;
647}
648
649static int pvcalls_back_handle_cmd(struct xenbus_device *dev,
650 struct xen_pvcalls_request *req)
651{
652 int ret = 0;
653
654 switch (req->cmd) {
655 case PVCALLS_SOCKET:
656 ret = pvcalls_back_socket(dev, req);
657 break;
658 case PVCALLS_CONNECT:
659 ret = pvcalls_back_connect(dev, req);
660 break;
661 case PVCALLS_RELEASE:
662 ret = pvcalls_back_release(dev, req);
663 break;
664 case PVCALLS_BIND:
665 ret = pvcalls_back_bind(dev, req);
666 break;
667 case PVCALLS_LISTEN:
668 ret = pvcalls_back_listen(dev, req);
669 break;
670 case PVCALLS_ACCEPT:
671 ret = pvcalls_back_accept(dev, req);
672 break;
673 case PVCALLS_POLL:
674 ret = pvcalls_back_poll(dev, req);
675 break;
676 default:
677 {
678 struct pvcalls_fedata *fedata;
679 struct xen_pvcalls_response *rsp;
680
681 fedata = dev_get_drvdata(&dev->dev);
682 rsp = RING_GET_RESPONSE(
683 &fedata->ring, fedata->ring.rsp_prod_pvt++);
684 rsp->req_id = req->req_id;
685 rsp->cmd = req->cmd;
686 rsp->ret = -ENOTSUPP;
687 break;
688 }
689 }
690 return ret;
691}
692
693static void pvcalls_back_work(struct pvcalls_fedata *fedata)
694{
695 int notify, notify_all = 0, more = 1;
696 struct xen_pvcalls_request req;
697 struct xenbus_device *dev = fedata->dev;
698
699 while (more) {
700 while (RING_HAS_UNCONSUMED_REQUESTS(&fedata->ring)) {
701 RING_COPY_REQUEST(&fedata->ring,
702 fedata->ring.req_cons++,
703 &req);
704
705 if (!pvcalls_back_handle_cmd(dev, &req)) {
706 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(
707 &fedata->ring, notify);
708 notify_all += notify;
709 }
710 }
711
712 if (notify_all) {
713 notify_remote_via_irq(fedata->irq);
714 notify_all = 0;
715 }
716
717 RING_FINAL_CHECK_FOR_REQUESTS(&fedata->ring, more);
718 }
719}
720
Stefano Stabellinid0e4d562017-07-06 10:59:29 -0700721static irqreturn_t pvcalls_back_event(int irq, void *dev_id)
722{
Stefano Stabellinib1efa692017-07-06 11:00:00 -0700723 struct xenbus_device *dev = dev_id;
724 struct pvcalls_fedata *fedata = NULL;
725
726 if (dev == NULL)
727 return IRQ_HANDLED;
728
729 fedata = dev_get_drvdata(&dev->dev);
730 if (fedata == NULL)
731 return IRQ_HANDLED;
732
733 pvcalls_back_work(fedata);
Stefano Stabellinid0e4d562017-07-06 10:59:29 -0700734 return IRQ_HANDLED;
735}
736
Stefano Stabellini5db4d282017-07-06 11:01:06 -0700737static irqreturn_t pvcalls_back_conn_event(int irq, void *sock_map)
738{
739 return IRQ_HANDLED;
740}
741
Stefano Stabellini0a9c75c2017-07-06 10:59:17 -0700742static int backend_connect(struct xenbus_device *dev)
743{
Stefano Stabellinid0e4d562017-07-06 10:59:29 -0700744 int err, evtchn;
745 grant_ref_t ring_ref;
746 struct pvcalls_fedata *fedata = NULL;
747
748 fedata = kzalloc(sizeof(struct pvcalls_fedata), GFP_KERNEL);
749 if (!fedata)
750 return -ENOMEM;
751
752 fedata->irq = -1;
753 err = xenbus_scanf(XBT_NIL, dev->otherend, "port", "%u",
754 &evtchn);
755 if (err != 1) {
756 err = -EINVAL;
757 xenbus_dev_fatal(dev, err, "reading %s/event-channel",
758 dev->otherend);
759 goto error;
760 }
761
762 err = xenbus_scanf(XBT_NIL, dev->otherend, "ring-ref", "%u", &ring_ref);
763 if (err != 1) {
764 err = -EINVAL;
765 xenbus_dev_fatal(dev, err, "reading %s/ring-ref",
766 dev->otherend);
767 goto error;
768 }
769
770 err = bind_interdomain_evtchn_to_irq(dev->otherend_id, evtchn);
771 if (err < 0)
772 goto error;
773 fedata->irq = err;
774
775 err = request_threaded_irq(fedata->irq, NULL, pvcalls_back_event,
776 IRQF_ONESHOT, "pvcalls-back", dev);
777 if (err < 0)
778 goto error;
779
780 err = xenbus_map_ring_valloc(dev, &ring_ref, 1,
781 (void **)&fedata->sring);
782 if (err < 0)
783 goto error;
784
785 BACK_RING_INIT(&fedata->ring, fedata->sring, XEN_PAGE_SIZE * 1);
786 fedata->dev = dev;
787
788 INIT_LIST_HEAD(&fedata->socket_mappings);
789 INIT_RADIX_TREE(&fedata->socketpass_mappings, GFP_KERNEL);
790 sema_init(&fedata->socket_lock, 1);
791 dev_set_drvdata(&dev->dev, fedata);
792
793 down(&pvcalls_back_global.frontends_lock);
794 list_add_tail(&fedata->list, &pvcalls_back_global.frontends);
795 up(&pvcalls_back_global.frontends_lock);
796
Stefano Stabellini0a9c75c2017-07-06 10:59:17 -0700797 return 0;
Stefano Stabellinid0e4d562017-07-06 10:59:29 -0700798
799 error:
800 if (fedata->irq >= 0)
801 unbind_from_irqhandler(fedata->irq, dev);
802 if (fedata->sring != NULL)
803 xenbus_unmap_ring_vfree(dev, fedata->sring);
804 kfree(fedata);
805 return err;
Stefano Stabellini0a9c75c2017-07-06 10:59:17 -0700806}
807
808static int backend_disconnect(struct xenbus_device *dev)
809{
Stefano Stabellini0a85d232017-07-06 11:01:07 -0700810 struct pvcalls_fedata *fedata;
811 struct sock_mapping *map, *n;
812 struct sockpass_mapping *mappass;
813 struct radix_tree_iter iter;
814 void **slot;
815
816
817 fedata = dev_get_drvdata(&dev->dev);
818
819 down(&fedata->socket_lock);
820 list_for_each_entry_safe(map, n, &fedata->socket_mappings, list) {
821 list_del(&map->list);
822 pvcalls_back_release_active(dev, fedata, map);
823 }
824
825 radix_tree_for_each_slot(slot, &fedata->socketpass_mappings, &iter, 0) {
826 mappass = radix_tree_deref_slot(slot);
827 if (!mappass)
828 continue;
829 if (radix_tree_exception(mappass)) {
830 if (radix_tree_deref_retry(mappass))
831 slot = radix_tree_iter_retry(&iter);
832 } else {
833 radix_tree_delete(&fedata->socketpass_mappings,
834 mappass->id);
835 pvcalls_back_release_passive(dev, fedata, mappass);
836 }
837 }
838 up(&fedata->socket_lock);
839
840 unbind_from_irqhandler(fedata->irq, dev);
841 xenbus_unmap_ring_vfree(dev, fedata->sring);
842
843 list_del(&fedata->list);
844 kfree(fedata);
845 dev_set_drvdata(&dev->dev, NULL);
846
Stefano Stabellini0a9c75c2017-07-06 10:59:17 -0700847 return 0;
848}
849
Stefano Stabellini72e59c32017-07-05 13:08:39 -0700850static int pvcalls_back_probe(struct xenbus_device *dev,
851 const struct xenbus_device_id *id)
852{
Stefano Stabellini0a9c75c2017-07-06 10:59:17 -0700853 int err, abort;
854 struct xenbus_transaction xbt;
855
856again:
857 abort = 1;
858
859 err = xenbus_transaction_start(&xbt);
860 if (err) {
861 pr_warn("%s cannot create xenstore transaction\n", __func__);
862 return err;
863 }
864
865 err = xenbus_printf(xbt, dev->nodename, "versions", "%s",
866 PVCALLS_VERSIONS);
867 if (err) {
868 pr_warn("%s write out 'versions' failed\n", __func__);
869 goto abort;
870 }
871
872 err = xenbus_printf(xbt, dev->nodename, "max-page-order", "%u",
873 MAX_RING_ORDER);
874 if (err) {
875 pr_warn("%s write out 'max-page-order' failed\n", __func__);
876 goto abort;
877 }
878
879 err = xenbus_printf(xbt, dev->nodename, "function-calls",
880 XENBUS_FUNCTIONS_CALLS);
881 if (err) {
882 pr_warn("%s write out 'function-calls' failed\n", __func__);
883 goto abort;
884 }
885
886 abort = 0;
887abort:
888 err = xenbus_transaction_end(xbt, abort);
889 if (err) {
890 if (err == -EAGAIN && !abort)
891 goto again;
892 pr_warn("%s cannot complete xenstore transaction\n", __func__);
893 return err;
894 }
895
896 if (abort)
897 return -EFAULT;
898
899 xenbus_switch_state(dev, XenbusStateInitWait);
900
Stefano Stabellini72e59c32017-07-05 13:08:39 -0700901 return 0;
902}
903
Stefano Stabellini0a9c75c2017-07-06 10:59:17 -0700904static void set_backend_state(struct xenbus_device *dev,
905 enum xenbus_state state)
906{
907 while (dev->state != state) {
908 switch (dev->state) {
909 case XenbusStateClosed:
910 switch (state) {
911 case XenbusStateInitWait:
912 case XenbusStateConnected:
913 xenbus_switch_state(dev, XenbusStateInitWait);
914 break;
915 case XenbusStateClosing:
916 xenbus_switch_state(dev, XenbusStateClosing);
917 break;
918 default:
919 __WARN();
920 }
921 break;
922 case XenbusStateInitWait:
923 case XenbusStateInitialised:
924 switch (state) {
925 case XenbusStateConnected:
926 backend_connect(dev);
927 xenbus_switch_state(dev, XenbusStateConnected);
928 break;
929 case XenbusStateClosing:
930 case XenbusStateClosed:
931 xenbus_switch_state(dev, XenbusStateClosing);
932 break;
933 default:
934 __WARN();
935 }
936 break;
937 case XenbusStateConnected:
938 switch (state) {
939 case XenbusStateInitWait:
940 case XenbusStateClosing:
941 case XenbusStateClosed:
942 down(&pvcalls_back_global.frontends_lock);
943 backend_disconnect(dev);
944 up(&pvcalls_back_global.frontends_lock);
945 xenbus_switch_state(dev, XenbusStateClosing);
946 break;
947 default:
948 __WARN();
949 }
950 break;
951 case XenbusStateClosing:
952 switch (state) {
953 case XenbusStateInitWait:
954 case XenbusStateConnected:
955 case XenbusStateClosed:
956 xenbus_switch_state(dev, XenbusStateClosed);
957 break;
958 default:
959 __WARN();
960 }
961 break;
962 default:
963 __WARN();
964 }
965 }
966}
967
Stefano Stabellini72e59c32017-07-05 13:08:39 -0700968static void pvcalls_back_changed(struct xenbus_device *dev,
969 enum xenbus_state frontend_state)
970{
Stefano Stabellini0a9c75c2017-07-06 10:59:17 -0700971 switch (frontend_state) {
972 case XenbusStateInitialising:
973 set_backend_state(dev, XenbusStateInitWait);
974 break;
975
976 case XenbusStateInitialised:
977 case XenbusStateConnected:
978 set_backend_state(dev, XenbusStateConnected);
979 break;
980
981 case XenbusStateClosing:
982 set_backend_state(dev, XenbusStateClosing);
983 break;
984
985 case XenbusStateClosed:
986 set_backend_state(dev, XenbusStateClosed);
987 if (xenbus_dev_is_online(dev))
988 break;
989 device_unregister(&dev->dev);
990 break;
991 case XenbusStateUnknown:
992 set_backend_state(dev, XenbusStateClosed);
993 device_unregister(&dev->dev);
994 break;
995
996 default:
997 xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
998 frontend_state);
999 break;
1000 }
Stefano Stabellini72e59c32017-07-05 13:08:39 -07001001}
1002
1003static int pvcalls_back_remove(struct xenbus_device *dev)
1004{
1005 return 0;
1006}
1007
1008static int pvcalls_back_uevent(struct xenbus_device *xdev,
1009 struct kobj_uevent_env *env)
1010{
1011 return 0;
1012}
1013
1014static const struct xenbus_device_id pvcalls_back_ids[] = {
1015 { "pvcalls" },
1016 { "" }
1017};
1018
1019static struct xenbus_driver pvcalls_back_driver = {
1020 .ids = pvcalls_back_ids,
1021 .probe = pvcalls_back_probe,
1022 .remove = pvcalls_back_remove,
1023 .uevent = pvcalls_back_uevent,
1024 .otherend_changed = pvcalls_back_changed,
1025};
Stefano Stabellini9be07332017-07-05 13:08:48 -07001026
1027static int __init pvcalls_back_init(void)
1028{
1029 int ret;
1030
1031 if (!xen_domain())
1032 return -ENODEV;
1033
1034 ret = xenbus_register_backend(&pvcalls_back_driver);
1035 if (ret < 0)
1036 return ret;
1037
1038 sema_init(&pvcalls_back_global.frontends_lock, 1);
1039 INIT_LIST_HEAD(&pvcalls_back_global.frontends);
1040 return 0;
1041}
1042module_init(pvcalls_back_init);
Stefano Stabellini0a85d232017-07-06 11:01:07 -07001043
1044static void __exit pvcalls_back_fin(void)
1045{
1046 struct pvcalls_fedata *fedata, *nfedata;
1047
1048 down(&pvcalls_back_global.frontends_lock);
1049 list_for_each_entry_safe(fedata, nfedata,
1050 &pvcalls_back_global.frontends, list) {
1051 backend_disconnect(fedata->dev);
1052 }
1053 up(&pvcalls_back_global.frontends_lock);
1054
1055 xenbus_unregister_driver(&pvcalls_back_driver);
1056}
1057
1058module_exit(pvcalls_back_fin);