1 /****************************************************************************** 2 * xenbus_comms.c 3 * 4 * Low level code to talks to Xen Store: ringbuffer and event channel. 5 * 6 * Copyright (C) 2005 Rusty Russell, IBM Corporation 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License version 2 10 * as published by the Free Software Foundation; or, when distributed 11 * separately from the Linux kernel or incorporated into other 12 * software packages, subject to the following license: 13 * 14 * Permission is hereby granted, free of charge, to any person obtaining a copy 15 * of this source file (the "Software"), to deal in the Software without 16 * restriction, including without limitation the rights to use, copy, modify, 17 * merge, publish, distribute, sublicense, and/or sell copies of the Software, 18 * and to permit persons to whom the Software is furnished to do so, subject to 19 * the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be included in 22 * all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 30 * IN THE SOFTWARE. 31 */ 32 33 #include <linux/wait.h> 34 #include <linux/interrupt.h> 35 #include <linux/sched.h> 36 #include <linux/err.h> 37 #include <xen/xenbus.h> 38 #include <asm/xen/hypervisor.h> 39 #include <xen/events.h> 40 #include <xen/page.h> 41 #include "xenbus_comms.h" 42 43 static int xenbus_irq; 44 45 static DECLARE_WORK(probe_work, xenbus_probe); 46 47 static DECLARE_WAIT_QUEUE_HEAD(xb_waitq); 48 49 static irqreturn_t wake_waiting(int irq, void *unused) 50 { 51 if (unlikely(xenstored_ready == 0)) { 52 xenstored_ready = 1; 53 schedule_work(&probe_work); 54 } 55 56 wake_up(&xb_waitq); 57 return IRQ_HANDLED; 58 } 59 60 static int check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod) 61 { 62 return ((prod - cons) <= XENSTORE_RING_SIZE); 63 } 64 65 static void *get_output_chunk(XENSTORE_RING_IDX cons, 66 XENSTORE_RING_IDX prod, 67 char *buf, uint32_t *len) 68 { 69 *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod); 70 if ((XENSTORE_RING_SIZE - (prod - cons)) < *len) 71 *len = XENSTORE_RING_SIZE - (prod - cons); 72 return buf + MASK_XENSTORE_IDX(prod); 73 } 74 75 static const void *get_input_chunk(XENSTORE_RING_IDX cons, 76 XENSTORE_RING_IDX prod, 77 const char *buf, uint32_t *len) 78 { 79 *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons); 80 if ((prod - cons) < *len) 81 *len = prod - cons; 82 return buf + MASK_XENSTORE_IDX(cons); 83 } 84 85 /** 86 * xb_write - low level write 87 * @data: buffer to send 88 * @len: length of buffer 89 * 90 * Returns 0 on success, error otherwise. 91 */ 92 int xb_write(const void *data, unsigned len) 93 { 94 struct xenstore_domain_interface *intf = xen_store_interface; 95 XENSTORE_RING_IDX cons, prod; 96 int rc; 97 98 while (len != 0) { 99 void *dst; 100 unsigned int avail; 101 102 rc = wait_event_interruptible( 103 xb_waitq, 104 (intf->req_prod - intf->req_cons) != 105 XENSTORE_RING_SIZE); 106 if (rc < 0) 107 return rc; 108 109 /* Read indexes, then verify. */ 110 cons = intf->req_cons; 111 prod = intf->req_prod; 112 if (!check_indexes(cons, prod)) { 113 intf->req_cons = intf->req_prod = 0; 114 return -EIO; 115 } 116 117 dst = get_output_chunk(cons, prod, intf->req, &avail); 118 if (avail == 0) 119 continue; 120 if (avail > len) 121 avail = len; 122 123 /* Must write data /after/ reading the consumer index. */ 124 mb(); 125 126 memcpy(dst, data, avail); 127 data += avail; 128 len -= avail; 129 130 /* Other side must not see new producer until data is there. */ 131 wmb(); 132 intf->req_prod += avail; 133 134 /* Implies mb(): other side will see the updated producer. */ 135 notify_remote_via_evtchn(xen_store_evtchn); 136 } 137 138 return 0; 139 } 140 141 int xb_data_to_read(void) 142 { 143 struct xenstore_domain_interface *intf = xen_store_interface; 144 return (intf->rsp_cons != intf->rsp_prod); 145 } 146 147 int xb_wait_for_data_to_read(void) 148 { 149 return wait_event_interruptible(xb_waitq, xb_data_to_read()); 150 } 151 152 int xb_read(void *data, unsigned len) 153 { 154 struct xenstore_domain_interface *intf = xen_store_interface; 155 XENSTORE_RING_IDX cons, prod; 156 int rc; 157 158 while (len != 0) { 159 unsigned int avail; 160 const char *src; 161 162 rc = xb_wait_for_data_to_read(); 163 if (rc < 0) 164 return rc; 165 166 /* Read indexes, then verify. */ 167 cons = intf->rsp_cons; 168 prod = intf->rsp_prod; 169 if (!check_indexes(cons, prod)) { 170 intf->rsp_cons = intf->rsp_prod = 0; 171 return -EIO; 172 } 173 174 src = get_input_chunk(cons, prod, intf->rsp, &avail); 175 if (avail == 0) 176 continue; 177 if (avail > len) 178 avail = len; 179 180 /* Must read data /after/ reading the producer index. */ 181 rmb(); 182 183 memcpy(data, src, avail); 184 data += avail; 185 len -= avail; 186 187 /* Other side must not see free space until we've copied out */ 188 mb(); 189 intf->rsp_cons += avail; 190 191 pr_debug("Finished read of %i bytes (%i to go)\n", avail, len); 192 193 /* Implies mb(): other side will see the updated consumer. */ 194 notify_remote_via_evtchn(xen_store_evtchn); 195 } 196 197 return 0; 198 } 199 200 /** 201 * xb_init_comms - Set up interrupt handler off store event channel. 202 */ 203 int xb_init_comms(void) 204 { 205 struct xenstore_domain_interface *intf = xen_store_interface; 206 int err; 207 208 if (intf->req_prod != intf->req_cons) 209 printk(KERN_ERR "XENBUS request ring is not quiescent " 210 "(%08x:%08x)!\n", intf->req_cons, intf->req_prod); 211 212 if (intf->rsp_prod != intf->rsp_cons) { 213 printk(KERN_WARNING "XENBUS response ring is not quiescent " 214 "(%08x:%08x): fixing up\n", 215 intf->rsp_cons, intf->rsp_prod); 216 intf->rsp_cons = intf->rsp_prod; 217 } 218 219 if (xenbus_irq) 220 unbind_from_irqhandler(xenbus_irq, &xb_waitq); 221 222 err = bind_evtchn_to_irqhandler( 223 xen_store_evtchn, wake_waiting, 224 0, "xenbus", &xb_waitq); 225 if (err <= 0) { 226 printk(KERN_ERR "XENBUS request irq failed %i\n", err); 227 return err; 228 } 229 230 xenbus_irq = err; 231 232 return 0; 233 } 234