1416efba0SStefano Stabellini /* 2416efba0SStefano Stabellini * (c) 2017 Stefano Stabellini <stefano@aporeto.com> 3416efba0SStefano Stabellini * 4416efba0SStefano Stabellini * This program is free software; you can redistribute it and/or modify 5416efba0SStefano Stabellini * it under the terms of the GNU General Public License as published by 6416efba0SStefano Stabellini * the Free Software Foundation; either version 2 of the License, or 7416efba0SStefano Stabellini * (at your option) any later version. 8416efba0SStefano Stabellini * 9416efba0SStefano Stabellini * This program is distributed in the hope that it will be useful, 10416efba0SStefano Stabellini * but WITHOUT ANY WARRANTY; without even the implied warranty of 11416efba0SStefano Stabellini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12416efba0SStefano Stabellini * GNU General Public License for more details. 13416efba0SStefano Stabellini */ 14416efba0SStefano Stabellini 15416efba0SStefano Stabellini #include <linux/module.h> 162195046bSStefano Stabellini #include <linux/net.h> 172195046bSStefano Stabellini #include <linux/socket.h> 182195046bSStefano Stabellini 192195046bSStefano Stabellini #include <net/sock.h> 20416efba0SStefano Stabellini 21416efba0SStefano Stabellini #include <xen/events.h> 22416efba0SStefano Stabellini #include <xen/grant_table.h> 23416efba0SStefano Stabellini #include <xen/xen.h> 24416efba0SStefano Stabellini #include <xen/xenbus.h> 25416efba0SStefano Stabellini #include <xen/interface/io/pvcalls.h> 26416efba0SStefano Stabellini 272195046bSStefano Stabellini #include "pvcalls-front.h" 282195046bSStefano Stabellini 29aa7ba376SStefano Stabellini #define PVCALLS_INVALID_ID UINT_MAX 30aa7ba376SStefano Stabellini #define PVCALLS_RING_ORDER XENBUS_MAX_RING_GRANT_ORDER 31aa7ba376SStefano Stabellini #define PVCALLS_NR_RSP_PER_RING __CONST_RING_SIZE(xen_pvcalls, XEN_PAGE_SIZE) 32aa7ba376SStefano Stabellini 33aa7ba376SStefano Stabellini struct pvcalls_bedata { 34aa7ba376SStefano Stabellini struct xen_pvcalls_front_ring ring; 35aa7ba376SStefano Stabellini grant_ref_t ref; 36aa7ba376SStefano Stabellini int irq; 37aa7ba376SStefano Stabellini 38aa7ba376SStefano Stabellini struct list_head socket_mappings; 39aa7ba376SStefano Stabellini spinlock_t socket_lock; 40aa7ba376SStefano Stabellini 41aa7ba376SStefano Stabellini wait_queue_head_t inflight_req; 42aa7ba376SStefano Stabellini struct xen_pvcalls_response rsp[PVCALLS_NR_RSP_PER_RING]; 43aa7ba376SStefano Stabellini }; 44aa7ba376SStefano Stabellini /* Only one front/back connection supported. */ 45aa7ba376SStefano Stabellini static struct xenbus_device *pvcalls_front_dev; 46aa7ba376SStefano Stabellini static atomic_t pvcalls_refcount; 47aa7ba376SStefano Stabellini 48aa7ba376SStefano Stabellini /* first increment refcount, then proceed */ 49aa7ba376SStefano Stabellini #define pvcalls_enter() { \ 50aa7ba376SStefano Stabellini atomic_inc(&pvcalls_refcount); \ 51aa7ba376SStefano Stabellini } 52aa7ba376SStefano Stabellini 53aa7ba376SStefano Stabellini /* first complete other operations, then decrement refcount */ 54aa7ba376SStefano Stabellini #define pvcalls_exit() { \ 55aa7ba376SStefano Stabellini atomic_dec(&pvcalls_refcount); \ 56aa7ba376SStefano Stabellini } 57aa7ba376SStefano Stabellini 58aa7ba376SStefano Stabellini struct sock_mapping { 59aa7ba376SStefano Stabellini bool active_socket; 60aa7ba376SStefano Stabellini struct list_head list; 61aa7ba376SStefano Stabellini struct socket *sock; 62*cb1c7d9bSStefano Stabellini union { 63*cb1c7d9bSStefano Stabellini struct { 64*cb1c7d9bSStefano Stabellini int irq; 65*cb1c7d9bSStefano Stabellini grant_ref_t ref; 66*cb1c7d9bSStefano Stabellini struct pvcalls_data_intf *ring; 67*cb1c7d9bSStefano Stabellini struct pvcalls_data data; 68*cb1c7d9bSStefano Stabellini struct mutex in_mutex; 69*cb1c7d9bSStefano Stabellini struct mutex out_mutex; 70*cb1c7d9bSStefano Stabellini 71*cb1c7d9bSStefano Stabellini wait_queue_head_t inflight_conn_req; 72*cb1c7d9bSStefano Stabellini } active; 73*cb1c7d9bSStefano Stabellini }; 74aa7ba376SStefano Stabellini }; 75aa7ba376SStefano Stabellini 762195046bSStefano Stabellini static inline int get_request(struct pvcalls_bedata *bedata, int *req_id) 772195046bSStefano Stabellini { 782195046bSStefano Stabellini *req_id = bedata->ring.req_prod_pvt & (RING_SIZE(&bedata->ring) - 1); 792195046bSStefano Stabellini if (RING_FULL(&bedata->ring) || 802195046bSStefano Stabellini bedata->rsp[*req_id].req_id != PVCALLS_INVALID_ID) 812195046bSStefano Stabellini return -EAGAIN; 822195046bSStefano Stabellini return 0; 832195046bSStefano Stabellini } 842195046bSStefano Stabellini 85aa7ba376SStefano Stabellini static irqreturn_t pvcalls_front_event_handler(int irq, void *dev_id) 86aa7ba376SStefano Stabellini { 872195046bSStefano Stabellini struct xenbus_device *dev = dev_id; 882195046bSStefano Stabellini struct pvcalls_bedata *bedata; 892195046bSStefano Stabellini struct xen_pvcalls_response *rsp; 902195046bSStefano Stabellini uint8_t *src, *dst; 912195046bSStefano Stabellini int req_id = 0, more = 0, done = 0; 922195046bSStefano Stabellini 932195046bSStefano Stabellini if (dev == NULL) 942195046bSStefano Stabellini return IRQ_HANDLED; 952195046bSStefano Stabellini 962195046bSStefano Stabellini pvcalls_enter(); 972195046bSStefano Stabellini bedata = dev_get_drvdata(&dev->dev); 982195046bSStefano Stabellini if (bedata == NULL) { 992195046bSStefano Stabellini pvcalls_exit(); 1002195046bSStefano Stabellini return IRQ_HANDLED; 1012195046bSStefano Stabellini } 1022195046bSStefano Stabellini 1032195046bSStefano Stabellini again: 1042195046bSStefano Stabellini while (RING_HAS_UNCONSUMED_RESPONSES(&bedata->ring)) { 1052195046bSStefano Stabellini rsp = RING_GET_RESPONSE(&bedata->ring, bedata->ring.rsp_cons); 1062195046bSStefano Stabellini 1072195046bSStefano Stabellini req_id = rsp->req_id; 1082195046bSStefano Stabellini dst = (uint8_t *)&bedata->rsp[req_id] + sizeof(rsp->req_id); 1092195046bSStefano Stabellini src = (uint8_t *)rsp + sizeof(rsp->req_id); 1102195046bSStefano Stabellini memcpy(dst, src, sizeof(*rsp) - sizeof(rsp->req_id)); 1112195046bSStefano Stabellini /* 1122195046bSStefano Stabellini * First copy the rest of the data, then req_id. It is 1132195046bSStefano Stabellini * paired with the barrier when accessing bedata->rsp. 1142195046bSStefano Stabellini */ 1152195046bSStefano Stabellini smp_wmb(); 1162195046bSStefano Stabellini bedata->rsp[req_id].req_id = rsp->req_id; 1172195046bSStefano Stabellini 1182195046bSStefano Stabellini done = 1; 1192195046bSStefano Stabellini bedata->ring.rsp_cons++; 1202195046bSStefano Stabellini } 1212195046bSStefano Stabellini 1222195046bSStefano Stabellini RING_FINAL_CHECK_FOR_RESPONSES(&bedata->ring, more); 1232195046bSStefano Stabellini if (more) 1242195046bSStefano Stabellini goto again; 1252195046bSStefano Stabellini if (done) 1262195046bSStefano Stabellini wake_up(&bedata->inflight_req); 1272195046bSStefano Stabellini pvcalls_exit(); 128aa7ba376SStefano Stabellini return IRQ_HANDLED; 129aa7ba376SStefano Stabellini } 130aa7ba376SStefano Stabellini 131aa7ba376SStefano Stabellini static void pvcalls_front_free_map(struct pvcalls_bedata *bedata, 132aa7ba376SStefano Stabellini struct sock_mapping *map) 133aa7ba376SStefano Stabellini { 134aa7ba376SStefano Stabellini } 135aa7ba376SStefano Stabellini 136*cb1c7d9bSStefano Stabellini static irqreturn_t pvcalls_front_conn_handler(int irq, void *sock_map) 137*cb1c7d9bSStefano Stabellini { 138*cb1c7d9bSStefano Stabellini struct sock_mapping *map = sock_map; 139*cb1c7d9bSStefano Stabellini 140*cb1c7d9bSStefano Stabellini if (map == NULL) 141*cb1c7d9bSStefano Stabellini return IRQ_HANDLED; 142*cb1c7d9bSStefano Stabellini 143*cb1c7d9bSStefano Stabellini wake_up_interruptible(&map->active.inflight_conn_req); 144*cb1c7d9bSStefano Stabellini 145*cb1c7d9bSStefano Stabellini return IRQ_HANDLED; 146*cb1c7d9bSStefano Stabellini } 147*cb1c7d9bSStefano Stabellini 1482195046bSStefano Stabellini int pvcalls_front_socket(struct socket *sock) 1492195046bSStefano Stabellini { 1502195046bSStefano Stabellini struct pvcalls_bedata *bedata; 1512195046bSStefano Stabellini struct sock_mapping *map = NULL; 1522195046bSStefano Stabellini struct xen_pvcalls_request *req; 1532195046bSStefano Stabellini int notify, req_id, ret; 1542195046bSStefano Stabellini 1552195046bSStefano Stabellini /* 1562195046bSStefano Stabellini * PVCalls only supports domain AF_INET, 1572195046bSStefano Stabellini * type SOCK_STREAM and protocol 0 sockets for now. 1582195046bSStefano Stabellini * 1592195046bSStefano Stabellini * Check socket type here, AF_INET and protocol checks are done 1602195046bSStefano Stabellini * by the caller. 1612195046bSStefano Stabellini */ 1622195046bSStefano Stabellini if (sock->type != SOCK_STREAM) 1632195046bSStefano Stabellini return -EOPNOTSUPP; 1642195046bSStefano Stabellini 1652195046bSStefano Stabellini pvcalls_enter(); 1662195046bSStefano Stabellini if (!pvcalls_front_dev) { 1672195046bSStefano Stabellini pvcalls_exit(); 1682195046bSStefano Stabellini return -EACCES; 1692195046bSStefano Stabellini } 1702195046bSStefano Stabellini bedata = dev_get_drvdata(&pvcalls_front_dev->dev); 1712195046bSStefano Stabellini 1722195046bSStefano Stabellini map = kzalloc(sizeof(*map), GFP_KERNEL); 1732195046bSStefano Stabellini if (map == NULL) { 1742195046bSStefano Stabellini pvcalls_exit(); 1752195046bSStefano Stabellini return -ENOMEM; 1762195046bSStefano Stabellini } 1772195046bSStefano Stabellini 1782195046bSStefano Stabellini spin_lock(&bedata->socket_lock); 1792195046bSStefano Stabellini 1802195046bSStefano Stabellini ret = get_request(bedata, &req_id); 1812195046bSStefano Stabellini if (ret < 0) { 1822195046bSStefano Stabellini kfree(map); 1832195046bSStefano Stabellini spin_unlock(&bedata->socket_lock); 1842195046bSStefano Stabellini pvcalls_exit(); 1852195046bSStefano Stabellini return ret; 1862195046bSStefano Stabellini } 1872195046bSStefano Stabellini 1882195046bSStefano Stabellini /* 1892195046bSStefano Stabellini * sock->sk->sk_send_head is not used for ip sockets: reuse the 1902195046bSStefano Stabellini * field to store a pointer to the struct sock_mapping 1912195046bSStefano Stabellini * corresponding to the socket. This way, we can easily get the 1922195046bSStefano Stabellini * struct sock_mapping from the struct socket. 1932195046bSStefano Stabellini */ 1942195046bSStefano Stabellini sock->sk->sk_send_head = (void *)map; 1952195046bSStefano Stabellini list_add_tail(&map->list, &bedata->socket_mappings); 1962195046bSStefano Stabellini 1972195046bSStefano Stabellini req = RING_GET_REQUEST(&bedata->ring, req_id); 1982195046bSStefano Stabellini req->req_id = req_id; 1992195046bSStefano Stabellini req->cmd = PVCALLS_SOCKET; 2002195046bSStefano Stabellini req->u.socket.id = (uintptr_t) map; 2012195046bSStefano Stabellini req->u.socket.domain = AF_INET; 2022195046bSStefano Stabellini req->u.socket.type = SOCK_STREAM; 2032195046bSStefano Stabellini req->u.socket.protocol = IPPROTO_IP; 2042195046bSStefano Stabellini 2052195046bSStefano Stabellini bedata->ring.req_prod_pvt++; 2062195046bSStefano Stabellini RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&bedata->ring, notify); 2072195046bSStefano Stabellini spin_unlock(&bedata->socket_lock); 2082195046bSStefano Stabellini if (notify) 2092195046bSStefano Stabellini notify_remote_via_irq(bedata->irq); 2102195046bSStefano Stabellini 2112195046bSStefano Stabellini wait_event(bedata->inflight_req, 2122195046bSStefano Stabellini READ_ONCE(bedata->rsp[req_id].req_id) == req_id); 2132195046bSStefano Stabellini 2142195046bSStefano Stabellini /* read req_id, then the content */ 2152195046bSStefano Stabellini smp_rmb(); 2162195046bSStefano Stabellini ret = bedata->rsp[req_id].ret; 2172195046bSStefano Stabellini bedata->rsp[req_id].req_id = PVCALLS_INVALID_ID; 2182195046bSStefano Stabellini 2192195046bSStefano Stabellini pvcalls_exit(); 2202195046bSStefano Stabellini return ret; 2212195046bSStefano Stabellini } 2222195046bSStefano Stabellini 223*cb1c7d9bSStefano Stabellini static int create_active(struct sock_mapping *map, int *evtchn) 224*cb1c7d9bSStefano Stabellini { 225*cb1c7d9bSStefano Stabellini void *bytes; 226*cb1c7d9bSStefano Stabellini int ret = -ENOMEM, irq = -1, i; 227*cb1c7d9bSStefano Stabellini 228*cb1c7d9bSStefano Stabellini *evtchn = -1; 229*cb1c7d9bSStefano Stabellini init_waitqueue_head(&map->active.inflight_conn_req); 230*cb1c7d9bSStefano Stabellini 231*cb1c7d9bSStefano Stabellini map->active.ring = (struct pvcalls_data_intf *) 232*cb1c7d9bSStefano Stabellini __get_free_page(GFP_KERNEL | __GFP_ZERO); 233*cb1c7d9bSStefano Stabellini if (map->active.ring == NULL) 234*cb1c7d9bSStefano Stabellini goto out_error; 235*cb1c7d9bSStefano Stabellini map->active.ring->ring_order = PVCALLS_RING_ORDER; 236*cb1c7d9bSStefano Stabellini bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 237*cb1c7d9bSStefano Stabellini PVCALLS_RING_ORDER); 238*cb1c7d9bSStefano Stabellini if (bytes == NULL) 239*cb1c7d9bSStefano Stabellini goto out_error; 240*cb1c7d9bSStefano Stabellini for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++) 241*cb1c7d9bSStefano Stabellini map->active.ring->ref[i] = gnttab_grant_foreign_access( 242*cb1c7d9bSStefano Stabellini pvcalls_front_dev->otherend_id, 243*cb1c7d9bSStefano Stabellini pfn_to_gfn(virt_to_pfn(bytes) + i), 0); 244*cb1c7d9bSStefano Stabellini 245*cb1c7d9bSStefano Stabellini map->active.ref = gnttab_grant_foreign_access( 246*cb1c7d9bSStefano Stabellini pvcalls_front_dev->otherend_id, 247*cb1c7d9bSStefano Stabellini pfn_to_gfn(virt_to_pfn((void *)map->active.ring)), 0); 248*cb1c7d9bSStefano Stabellini 249*cb1c7d9bSStefano Stabellini map->active.data.in = bytes; 250*cb1c7d9bSStefano Stabellini map->active.data.out = bytes + 251*cb1c7d9bSStefano Stabellini XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER); 252*cb1c7d9bSStefano Stabellini 253*cb1c7d9bSStefano Stabellini ret = xenbus_alloc_evtchn(pvcalls_front_dev, evtchn); 254*cb1c7d9bSStefano Stabellini if (ret) 255*cb1c7d9bSStefano Stabellini goto out_error; 256*cb1c7d9bSStefano Stabellini irq = bind_evtchn_to_irqhandler(*evtchn, pvcalls_front_conn_handler, 257*cb1c7d9bSStefano Stabellini 0, "pvcalls-frontend", map); 258*cb1c7d9bSStefano Stabellini if (irq < 0) { 259*cb1c7d9bSStefano Stabellini ret = irq; 260*cb1c7d9bSStefano Stabellini goto out_error; 261*cb1c7d9bSStefano Stabellini } 262*cb1c7d9bSStefano Stabellini 263*cb1c7d9bSStefano Stabellini map->active.irq = irq; 264*cb1c7d9bSStefano Stabellini map->active_socket = true; 265*cb1c7d9bSStefano Stabellini mutex_init(&map->active.in_mutex); 266*cb1c7d9bSStefano Stabellini mutex_init(&map->active.out_mutex); 267*cb1c7d9bSStefano Stabellini 268*cb1c7d9bSStefano Stabellini return 0; 269*cb1c7d9bSStefano Stabellini 270*cb1c7d9bSStefano Stabellini out_error: 271*cb1c7d9bSStefano Stabellini if (irq >= 0) 272*cb1c7d9bSStefano Stabellini unbind_from_irqhandler(irq, map); 273*cb1c7d9bSStefano Stabellini else if (*evtchn >= 0) 274*cb1c7d9bSStefano Stabellini xenbus_free_evtchn(pvcalls_front_dev, *evtchn); 275*cb1c7d9bSStefano Stabellini kfree(map->active.data.in); 276*cb1c7d9bSStefano Stabellini kfree(map->active.ring); 277*cb1c7d9bSStefano Stabellini return ret; 278*cb1c7d9bSStefano Stabellini } 279*cb1c7d9bSStefano Stabellini 280*cb1c7d9bSStefano Stabellini int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr, 281*cb1c7d9bSStefano Stabellini int addr_len, int flags) 282*cb1c7d9bSStefano Stabellini { 283*cb1c7d9bSStefano Stabellini struct pvcalls_bedata *bedata; 284*cb1c7d9bSStefano Stabellini struct sock_mapping *map = NULL; 285*cb1c7d9bSStefano Stabellini struct xen_pvcalls_request *req; 286*cb1c7d9bSStefano Stabellini int notify, req_id, ret, evtchn; 287*cb1c7d9bSStefano Stabellini 288*cb1c7d9bSStefano Stabellini if (addr->sa_family != AF_INET || sock->type != SOCK_STREAM) 289*cb1c7d9bSStefano Stabellini return -EOPNOTSUPP; 290*cb1c7d9bSStefano Stabellini 291*cb1c7d9bSStefano Stabellini pvcalls_enter(); 292*cb1c7d9bSStefano Stabellini if (!pvcalls_front_dev) { 293*cb1c7d9bSStefano Stabellini pvcalls_exit(); 294*cb1c7d9bSStefano Stabellini return -ENOTCONN; 295*cb1c7d9bSStefano Stabellini } 296*cb1c7d9bSStefano Stabellini 297*cb1c7d9bSStefano Stabellini bedata = dev_get_drvdata(&pvcalls_front_dev->dev); 298*cb1c7d9bSStefano Stabellini 299*cb1c7d9bSStefano Stabellini map = (struct sock_mapping *)sock->sk->sk_send_head; 300*cb1c7d9bSStefano Stabellini if (!map) { 301*cb1c7d9bSStefano Stabellini pvcalls_exit(); 302*cb1c7d9bSStefano Stabellini return -ENOTSOCK; 303*cb1c7d9bSStefano Stabellini } 304*cb1c7d9bSStefano Stabellini 305*cb1c7d9bSStefano Stabellini spin_lock(&bedata->socket_lock); 306*cb1c7d9bSStefano Stabellini ret = get_request(bedata, &req_id); 307*cb1c7d9bSStefano Stabellini if (ret < 0) { 308*cb1c7d9bSStefano Stabellini spin_unlock(&bedata->socket_lock); 309*cb1c7d9bSStefano Stabellini pvcalls_exit(); 310*cb1c7d9bSStefano Stabellini return ret; 311*cb1c7d9bSStefano Stabellini } 312*cb1c7d9bSStefano Stabellini ret = create_active(map, &evtchn); 313*cb1c7d9bSStefano Stabellini if (ret < 0) { 314*cb1c7d9bSStefano Stabellini spin_unlock(&bedata->socket_lock); 315*cb1c7d9bSStefano Stabellini pvcalls_exit(); 316*cb1c7d9bSStefano Stabellini return ret; 317*cb1c7d9bSStefano Stabellini } 318*cb1c7d9bSStefano Stabellini 319*cb1c7d9bSStefano Stabellini req = RING_GET_REQUEST(&bedata->ring, req_id); 320*cb1c7d9bSStefano Stabellini req->req_id = req_id; 321*cb1c7d9bSStefano Stabellini req->cmd = PVCALLS_CONNECT; 322*cb1c7d9bSStefano Stabellini req->u.connect.id = (uintptr_t)map; 323*cb1c7d9bSStefano Stabellini req->u.connect.len = addr_len; 324*cb1c7d9bSStefano Stabellini req->u.connect.flags = flags; 325*cb1c7d9bSStefano Stabellini req->u.connect.ref = map->active.ref; 326*cb1c7d9bSStefano Stabellini req->u.connect.evtchn = evtchn; 327*cb1c7d9bSStefano Stabellini memcpy(req->u.connect.addr, addr, sizeof(*addr)); 328*cb1c7d9bSStefano Stabellini 329*cb1c7d9bSStefano Stabellini map->sock = sock; 330*cb1c7d9bSStefano Stabellini 331*cb1c7d9bSStefano Stabellini bedata->ring.req_prod_pvt++; 332*cb1c7d9bSStefano Stabellini RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&bedata->ring, notify); 333*cb1c7d9bSStefano Stabellini spin_unlock(&bedata->socket_lock); 334*cb1c7d9bSStefano Stabellini 335*cb1c7d9bSStefano Stabellini if (notify) 336*cb1c7d9bSStefano Stabellini notify_remote_via_irq(bedata->irq); 337*cb1c7d9bSStefano Stabellini 338*cb1c7d9bSStefano Stabellini wait_event(bedata->inflight_req, 339*cb1c7d9bSStefano Stabellini READ_ONCE(bedata->rsp[req_id].req_id) == req_id); 340*cb1c7d9bSStefano Stabellini 341*cb1c7d9bSStefano Stabellini /* read req_id, then the content */ 342*cb1c7d9bSStefano Stabellini smp_rmb(); 343*cb1c7d9bSStefano Stabellini ret = bedata->rsp[req_id].ret; 344*cb1c7d9bSStefano Stabellini bedata->rsp[req_id].req_id = PVCALLS_INVALID_ID; 345*cb1c7d9bSStefano Stabellini pvcalls_exit(); 346*cb1c7d9bSStefano Stabellini return ret; 347*cb1c7d9bSStefano Stabellini } 348*cb1c7d9bSStefano Stabellini 349416efba0SStefano Stabellini static const struct xenbus_device_id pvcalls_front_ids[] = { 350416efba0SStefano Stabellini { "pvcalls" }, 351416efba0SStefano Stabellini { "" } 352416efba0SStefano Stabellini }; 353416efba0SStefano Stabellini 354416efba0SStefano Stabellini static int pvcalls_front_remove(struct xenbus_device *dev) 355416efba0SStefano Stabellini { 356aa7ba376SStefano Stabellini struct pvcalls_bedata *bedata; 357aa7ba376SStefano Stabellini struct sock_mapping *map = NULL, *n; 358aa7ba376SStefano Stabellini 359aa7ba376SStefano Stabellini bedata = dev_get_drvdata(&pvcalls_front_dev->dev); 360aa7ba376SStefano Stabellini dev_set_drvdata(&dev->dev, NULL); 361aa7ba376SStefano Stabellini pvcalls_front_dev = NULL; 362aa7ba376SStefano Stabellini if (bedata->irq >= 0) 363aa7ba376SStefano Stabellini unbind_from_irqhandler(bedata->irq, dev); 364aa7ba376SStefano Stabellini 365*cb1c7d9bSStefano Stabellini list_for_each_entry_safe(map, n, &bedata->socket_mappings, list) { 366*cb1c7d9bSStefano Stabellini map->sock->sk->sk_send_head = NULL; 367*cb1c7d9bSStefano Stabellini if (map->active_socket) { 368*cb1c7d9bSStefano Stabellini map->active.ring->in_error = -EBADF; 369*cb1c7d9bSStefano Stabellini wake_up_interruptible(&map->active.inflight_conn_req); 370*cb1c7d9bSStefano Stabellini } 371*cb1c7d9bSStefano Stabellini } 372*cb1c7d9bSStefano Stabellini 373aa7ba376SStefano Stabellini smp_mb(); 374aa7ba376SStefano Stabellini while (atomic_read(&pvcalls_refcount) > 0) 375aa7ba376SStefano Stabellini cpu_relax(); 376aa7ba376SStefano Stabellini list_for_each_entry_safe(map, n, &bedata->socket_mappings, list) { 377aa7ba376SStefano Stabellini if (map->active_socket) { 378aa7ba376SStefano Stabellini /* No need to lock, refcount is 0 */ 379aa7ba376SStefano Stabellini pvcalls_front_free_map(bedata, map); 380aa7ba376SStefano Stabellini } else { 381aa7ba376SStefano Stabellini list_del(&map->list); 382aa7ba376SStefano Stabellini kfree(map); 383aa7ba376SStefano Stabellini } 384aa7ba376SStefano Stabellini } 385aa7ba376SStefano Stabellini if (bedata->ref >= 0) 386aa7ba376SStefano Stabellini gnttab_end_foreign_access(bedata->ref, 0, 0); 387aa7ba376SStefano Stabellini kfree(bedata->ring.sring); 388aa7ba376SStefano Stabellini kfree(bedata); 389aa7ba376SStefano Stabellini xenbus_switch_state(dev, XenbusStateClosed); 390416efba0SStefano Stabellini return 0; 391416efba0SStefano Stabellini } 392416efba0SStefano Stabellini 393416efba0SStefano Stabellini static int pvcalls_front_probe(struct xenbus_device *dev, 394416efba0SStefano Stabellini const struct xenbus_device_id *id) 395416efba0SStefano Stabellini { 39621968190SStefano Stabellini int ret = -ENOMEM, evtchn, i; 39721968190SStefano Stabellini unsigned int max_page_order, function_calls, len; 39821968190SStefano Stabellini char *versions; 39921968190SStefano Stabellini grant_ref_t gref_head = 0; 40021968190SStefano Stabellini struct xenbus_transaction xbt; 40121968190SStefano Stabellini struct pvcalls_bedata *bedata = NULL; 40221968190SStefano Stabellini struct xen_pvcalls_sring *sring; 40321968190SStefano Stabellini 40421968190SStefano Stabellini if (pvcalls_front_dev != NULL) { 40521968190SStefano Stabellini dev_err(&dev->dev, "only one PV Calls connection supported\n"); 40621968190SStefano Stabellini return -EINVAL; 40721968190SStefano Stabellini } 40821968190SStefano Stabellini 40921968190SStefano Stabellini versions = xenbus_read(XBT_NIL, dev->otherend, "versions", &len); 41021968190SStefano Stabellini if (!len) 41121968190SStefano Stabellini return -EINVAL; 41221968190SStefano Stabellini if (strcmp(versions, "1")) { 41321968190SStefano Stabellini kfree(versions); 41421968190SStefano Stabellini return -EINVAL; 41521968190SStefano Stabellini } 41621968190SStefano Stabellini kfree(versions); 41721968190SStefano Stabellini max_page_order = xenbus_read_unsigned(dev->otherend, 41821968190SStefano Stabellini "max-page-order", 0); 41921968190SStefano Stabellini if (max_page_order < PVCALLS_RING_ORDER) 42021968190SStefano Stabellini return -ENODEV; 42121968190SStefano Stabellini function_calls = xenbus_read_unsigned(dev->otherend, 42221968190SStefano Stabellini "function-calls", 0); 42321968190SStefano Stabellini /* See XENBUS_FUNCTIONS_CALLS in pvcalls.h */ 42421968190SStefano Stabellini if (function_calls != 1) 42521968190SStefano Stabellini return -ENODEV; 42621968190SStefano Stabellini pr_info("%s max-page-order is %u\n", __func__, max_page_order); 42721968190SStefano Stabellini 42821968190SStefano Stabellini bedata = kzalloc(sizeof(struct pvcalls_bedata), GFP_KERNEL); 42921968190SStefano Stabellini if (!bedata) 43021968190SStefano Stabellini return -ENOMEM; 43121968190SStefano Stabellini 43221968190SStefano Stabellini dev_set_drvdata(&dev->dev, bedata); 43321968190SStefano Stabellini pvcalls_front_dev = dev; 43421968190SStefano Stabellini init_waitqueue_head(&bedata->inflight_req); 43521968190SStefano Stabellini INIT_LIST_HEAD(&bedata->socket_mappings); 43621968190SStefano Stabellini spin_lock_init(&bedata->socket_lock); 43721968190SStefano Stabellini bedata->irq = -1; 43821968190SStefano Stabellini bedata->ref = -1; 43921968190SStefano Stabellini 44021968190SStefano Stabellini for (i = 0; i < PVCALLS_NR_RSP_PER_RING; i++) 44121968190SStefano Stabellini bedata->rsp[i].req_id = PVCALLS_INVALID_ID; 44221968190SStefano Stabellini 44321968190SStefano Stabellini sring = (struct xen_pvcalls_sring *) __get_free_page(GFP_KERNEL | 44421968190SStefano Stabellini __GFP_ZERO); 44521968190SStefano Stabellini if (!sring) 44621968190SStefano Stabellini goto error; 44721968190SStefano Stabellini SHARED_RING_INIT(sring); 44821968190SStefano Stabellini FRONT_RING_INIT(&bedata->ring, sring, XEN_PAGE_SIZE); 44921968190SStefano Stabellini 45021968190SStefano Stabellini ret = xenbus_alloc_evtchn(dev, &evtchn); 45121968190SStefano Stabellini if (ret) 45221968190SStefano Stabellini goto error; 45321968190SStefano Stabellini 45421968190SStefano Stabellini bedata->irq = bind_evtchn_to_irqhandler(evtchn, 45521968190SStefano Stabellini pvcalls_front_event_handler, 45621968190SStefano Stabellini 0, "pvcalls-frontend", dev); 45721968190SStefano Stabellini if (bedata->irq < 0) { 45821968190SStefano Stabellini ret = bedata->irq; 45921968190SStefano Stabellini goto error; 46021968190SStefano Stabellini } 46121968190SStefano Stabellini 46221968190SStefano Stabellini ret = gnttab_alloc_grant_references(1, &gref_head); 46321968190SStefano Stabellini if (ret < 0) 46421968190SStefano Stabellini goto error; 46521968190SStefano Stabellini bedata->ref = gnttab_claim_grant_reference(&gref_head); 46621968190SStefano Stabellini if (bedata->ref < 0) { 46721968190SStefano Stabellini ret = bedata->ref; 46821968190SStefano Stabellini goto error; 46921968190SStefano Stabellini } 47021968190SStefano Stabellini gnttab_grant_foreign_access_ref(bedata->ref, dev->otherend_id, 47121968190SStefano Stabellini virt_to_gfn((void *)sring), 0); 47221968190SStefano Stabellini 47321968190SStefano Stabellini again: 47421968190SStefano Stabellini ret = xenbus_transaction_start(&xbt); 47521968190SStefano Stabellini if (ret) { 47621968190SStefano Stabellini xenbus_dev_fatal(dev, ret, "starting transaction"); 47721968190SStefano Stabellini goto error; 47821968190SStefano Stabellini } 47921968190SStefano Stabellini ret = xenbus_printf(xbt, dev->nodename, "version", "%u", 1); 48021968190SStefano Stabellini if (ret) 48121968190SStefano Stabellini goto error_xenbus; 48221968190SStefano Stabellini ret = xenbus_printf(xbt, dev->nodename, "ring-ref", "%d", bedata->ref); 48321968190SStefano Stabellini if (ret) 48421968190SStefano Stabellini goto error_xenbus; 48521968190SStefano Stabellini ret = xenbus_printf(xbt, dev->nodename, "port", "%u", 48621968190SStefano Stabellini evtchn); 48721968190SStefano Stabellini if (ret) 48821968190SStefano Stabellini goto error_xenbus; 48921968190SStefano Stabellini ret = xenbus_transaction_end(xbt, 0); 49021968190SStefano Stabellini if (ret) { 49121968190SStefano Stabellini if (ret == -EAGAIN) 49221968190SStefano Stabellini goto again; 49321968190SStefano Stabellini xenbus_dev_fatal(dev, ret, "completing transaction"); 49421968190SStefano Stabellini goto error; 49521968190SStefano Stabellini } 49621968190SStefano Stabellini xenbus_switch_state(dev, XenbusStateInitialised); 49721968190SStefano Stabellini 498416efba0SStefano Stabellini return 0; 49921968190SStefano Stabellini 50021968190SStefano Stabellini error_xenbus: 50121968190SStefano Stabellini xenbus_transaction_end(xbt, 1); 50221968190SStefano Stabellini xenbus_dev_fatal(dev, ret, "writing xenstore"); 50321968190SStefano Stabellini error: 50421968190SStefano Stabellini pvcalls_front_remove(dev); 50521968190SStefano Stabellini return ret; 506416efba0SStefano Stabellini } 507416efba0SStefano Stabellini 508416efba0SStefano Stabellini static void pvcalls_front_changed(struct xenbus_device *dev, 509416efba0SStefano Stabellini enum xenbus_state backend_state) 510416efba0SStefano Stabellini { 51121968190SStefano Stabellini switch (backend_state) { 51221968190SStefano Stabellini case XenbusStateReconfiguring: 51321968190SStefano Stabellini case XenbusStateReconfigured: 51421968190SStefano Stabellini case XenbusStateInitialising: 51521968190SStefano Stabellini case XenbusStateInitialised: 51621968190SStefano Stabellini case XenbusStateUnknown: 51721968190SStefano Stabellini break; 51821968190SStefano Stabellini 51921968190SStefano Stabellini case XenbusStateInitWait: 52021968190SStefano Stabellini break; 52121968190SStefano Stabellini 52221968190SStefano Stabellini case XenbusStateConnected: 52321968190SStefano Stabellini xenbus_switch_state(dev, XenbusStateConnected); 52421968190SStefano Stabellini break; 52521968190SStefano Stabellini 52621968190SStefano Stabellini case XenbusStateClosed: 52721968190SStefano Stabellini if (dev->state == XenbusStateClosed) 52821968190SStefano Stabellini break; 52921968190SStefano Stabellini /* Missed the backend's CLOSING state -- fallthrough */ 53021968190SStefano Stabellini case XenbusStateClosing: 53121968190SStefano Stabellini xenbus_frontend_closed(dev); 53221968190SStefano Stabellini break; 53321968190SStefano Stabellini } 534416efba0SStefano Stabellini } 535416efba0SStefano Stabellini 536416efba0SStefano Stabellini static struct xenbus_driver pvcalls_front_driver = { 537416efba0SStefano Stabellini .ids = pvcalls_front_ids, 538416efba0SStefano Stabellini .probe = pvcalls_front_probe, 539416efba0SStefano Stabellini .remove = pvcalls_front_remove, 540416efba0SStefano Stabellini .otherend_changed = pvcalls_front_changed, 541416efba0SStefano Stabellini }; 542416efba0SStefano Stabellini 543416efba0SStefano Stabellini static int __init pvcalls_frontend_init(void) 544416efba0SStefano Stabellini { 545416efba0SStefano Stabellini if (!xen_domain()) 546416efba0SStefano Stabellini return -ENODEV; 547416efba0SStefano Stabellini 548416efba0SStefano Stabellini pr_info("Initialising Xen pvcalls frontend driver\n"); 549416efba0SStefano Stabellini 550416efba0SStefano Stabellini return xenbus_register_frontend(&pvcalls_front_driver); 551416efba0SStefano Stabellini } 552416efba0SStefano Stabellini 553416efba0SStefano Stabellini module_init(pvcalls_frontend_init); 554