ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c @ 6538:84ee014ebd41

Merge xen-vtx-unstable.hg
author adsharma@los-vmm.sc.intel.com
date Wed Aug 17 12:34:38 2005 -0800 (2005-08-17)
parents 23979fb12c49 f46bb706a38d
children 99914b54f7bf
line source
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 file may be distributed separately from the Linux kernel, or
9 * incorporated into other software packages, subject to the following license:
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this source file (the "Software"), to deal in the Software without
13 * restriction, including without limitation the rights to use, copy, modify,
14 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
15 * and to permit persons to whom the Software is furnished to do so, subject to
16 * the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
27 * IN THE SOFTWARE.
28 */
30 #include <asm-xen/hypervisor.h>
31 #include <asm-xen/evtchn.h>
32 #include <linux/wait.h>
33 #include <linux/interrupt.h>
34 #include <linux/sched.h>
35 #include <linux/err.h>
36 #include "xenbus_comms.h"
38 #define RINGBUF_DATASIZE ((PAGE_SIZE / 2) - sizeof(struct ringbuf_head))
39 struct ringbuf_head
40 {
41 u32 write; /* Next place to write to */
42 u32 read; /* Next place to read from */
43 u8 flags;
44 char buf[0];
45 } __attribute__((packed));
47 DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
49 static inline struct ringbuf_head *outbuf(void)
50 {
51 return machine_to_virt(xen_start_info.store_mfn << PAGE_SHIFT);
52 }
54 static inline struct ringbuf_head *inbuf(void)
55 {
56 return machine_to_virt(xen_start_info.store_mfn << PAGE_SHIFT)
57 + PAGE_SIZE/2;
58 }
60 static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs)
61 {
62 wake_up(&xb_waitq);
63 return IRQ_HANDLED;
64 }
66 static int check_buffer(const struct ringbuf_head *h)
67 {
68 return (h->write < RINGBUF_DATASIZE && h->read < RINGBUF_DATASIZE);
69 }
71 /* We can't fill last byte: would look like empty buffer. */
72 static void *get_output_chunk(const struct ringbuf_head *h,
73 void *buf, u32 *len)
74 {
75 u32 read_mark;
77 if (h->read == 0)
78 read_mark = RINGBUF_DATASIZE - 1;
79 else
80 read_mark = h->read - 1;
82 /* Here to the end of buffer, unless they haven't read some out. */
83 *len = RINGBUF_DATASIZE - h->write;
84 if (read_mark >= h->write)
85 *len = read_mark - h->write;
86 return buf + h->write;
87 }
89 static const void *get_input_chunk(const struct ringbuf_head *h,
90 const void *buf, u32 *len)
91 {
92 /* Here to the end of buffer, unless they haven't written some. */
93 *len = RINGBUF_DATASIZE - h->read;
94 if (h->write >= h->read)
95 *len = h->write - h->read;
96 return buf + h->read;
97 }
99 static void update_output_chunk(struct ringbuf_head *h, u32 len)
100 {
101 h->write += len;
102 if (h->write == RINGBUF_DATASIZE)
103 h->write = 0;
104 }
106 static void update_input_chunk(struct ringbuf_head *h, u32 len)
107 {
108 h->read += len;
109 if (h->read == RINGBUF_DATASIZE)
110 h->read = 0;
111 }
113 static int output_avail(struct ringbuf_head *out)
114 {
115 unsigned int avail;
117 get_output_chunk(out, out->buf, &avail);
118 return avail != 0;
119 }
121 int xb_write(const void *data, unsigned len)
122 {
123 struct ringbuf_head h;
124 struct ringbuf_head *out = outbuf();
126 do {
127 void *dst;
128 unsigned int avail;
130 wait_event(xb_waitq, output_avail(out));
132 /* Read, then check: not that we don't trust store.
133 * Hell, some of my best friends are daemons. But,
134 * in this post-911 world... */
135 h = *out;
136 mb();
137 if (!check_buffer(&h)) {
138 set_current_state(TASK_RUNNING);
139 return -EIO; /* ETERRORIST! */
140 }
142 dst = get_output_chunk(&h, out->buf, &avail);
143 if (avail > len)
144 avail = len;
145 memcpy(dst, data, avail);
146 data += avail;
147 len -= avail;
148 update_output_chunk(out, avail);
149 notify_via_evtchn(xen_start_info.store_evtchn);
150 } while (len != 0);
152 return 0;
153 }
155 int xs_input_avail(void)
156 {
157 unsigned int avail;
158 struct ringbuf_head *in = inbuf();
160 get_input_chunk(in, in->buf, &avail);
161 return avail != 0;
162 }
164 int xb_read(void *data, unsigned len)
165 {
166 struct ringbuf_head h;
167 struct ringbuf_head *in = inbuf();
168 int was_full;
170 while (len != 0) {
171 unsigned int avail;
172 const char *src;
174 wait_event(xb_waitq, xs_input_avail());
175 h = *in;
176 mb();
177 if (!check_buffer(&h)) {
178 set_current_state(TASK_RUNNING);
179 return -EIO;
180 }
182 src = get_input_chunk(&h, in->buf, &avail);
183 if (avail > len)
184 avail = len;
185 was_full = !output_avail(&h);
187 memcpy(data, src, avail);
188 data += avail;
189 len -= avail;
190 update_input_chunk(in, avail);
191 pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
192 /* If it was full, tell them we've taken some. */
193 if (was_full)
194 notify_via_evtchn(xen_start_info.store_evtchn);
195 }
197 /* If we left something, wake watch thread to deal with it. */
198 if (xs_input_avail())
199 wake_up(&xb_waitq);
201 return 0;
202 }
204 /* Set up interrupt handler off store event channel. */
205 int xb_init_comms(void)
206 {
207 int err;
209 if (!xen_start_info.store_evtchn)
210 return 0;
212 err = bind_evtchn_to_irqhandler(
213 xen_start_info.store_evtchn, wake_waiting,
214 0, "xenbus", &xb_waitq);
215 if (err) {
216 printk(KERN_ERR "XENBUS request irq failed %i\n", err);
217 unbind_evtchn_from_irq(xen_start_info.store_evtchn);
218 return err;
219 }
221 /* FIXME zero out page -- domain builder should probably do this*/
222 memset(machine_to_virt(xen_start_info.store_mfn << PAGE_SHIFT),
223 0, PAGE_SIZE);
225 return 0;
226 }
228 void xb_suspend_comms(void)
229 {
231 if (!xen_start_info.store_evtchn)
232 return;
234 unbind_evtchn_from_irqhandler(xen_start_info.store_evtchn, &xb_waitq);
235 }