ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c @ 6294:1a0723cd37f1

Fix many uses of machine addresses in XenLinux. Primarily
this fixes users of virt_to_machine/machine_to_virt to
use virt_to_mfn/mfn_to_virt where that is more appropriate.

This should be a big step to improved PAE stability.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Aug 19 16:06:43 2005 +0000 (2005-08-19)
parents f46bb706a38d
children f51fe43c5d1c 5f4724c13040 81576d3d1ca8 3a8f27c6d56c
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 mfn_to_virt(xen_start_info.store_mfn);
52 }
54 static inline struct ringbuf_head *inbuf(void)
55 {
56 return mfn_to_virt(xen_start_info.store_mfn) + PAGE_SIZE/2;
57 }
59 static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs)
60 {
61 wake_up(&xb_waitq);
62 return IRQ_HANDLED;
63 }
65 static int check_buffer(const struct ringbuf_head *h)
66 {
67 return (h->write < RINGBUF_DATASIZE && h->read < RINGBUF_DATASIZE);
68 }
70 /* We can't fill last byte: would look like empty buffer. */
71 static void *get_output_chunk(const struct ringbuf_head *h,
72 void *buf, u32 *len)
73 {
74 u32 read_mark;
76 if (h->read == 0)
77 read_mark = RINGBUF_DATASIZE - 1;
78 else
79 read_mark = h->read - 1;
81 /* Here to the end of buffer, unless they haven't read some out. */
82 *len = RINGBUF_DATASIZE - h->write;
83 if (read_mark >= h->write)
84 *len = read_mark - h->write;
85 return buf + h->write;
86 }
88 static const void *get_input_chunk(const struct ringbuf_head *h,
89 const void *buf, u32 *len)
90 {
91 /* Here to the end of buffer, unless they haven't written some. */
92 *len = RINGBUF_DATASIZE - h->read;
93 if (h->write >= h->read)
94 *len = h->write - h->read;
95 return buf + h->read;
96 }
98 static void update_output_chunk(struct ringbuf_head *h, u32 len)
99 {
100 h->write += len;
101 if (h->write == RINGBUF_DATASIZE)
102 h->write = 0;
103 }
105 static void update_input_chunk(struct ringbuf_head *h, u32 len)
106 {
107 h->read += len;
108 if (h->read == RINGBUF_DATASIZE)
109 h->read = 0;
110 }
112 static int output_avail(struct ringbuf_head *out)
113 {
114 unsigned int avail;
116 get_output_chunk(out, out->buf, &avail);
117 return avail != 0;
118 }
120 int xb_write(const void *data, unsigned len)
121 {
122 struct ringbuf_head h;
123 struct ringbuf_head *out = outbuf();
125 do {
126 void *dst;
127 unsigned int avail;
129 wait_event(xb_waitq, output_avail(out));
131 /* Read, then check: not that we don't trust store.
132 * Hell, some of my best friends are daemons. But,
133 * in this post-911 world... */
134 h = *out;
135 mb();
136 if (!check_buffer(&h)) {
137 set_current_state(TASK_RUNNING);
138 return -EIO; /* ETERRORIST! */
139 }
141 dst = get_output_chunk(&h, out->buf, &avail);
142 if (avail > len)
143 avail = len;
144 memcpy(dst, data, avail);
145 data += avail;
146 len -= avail;
147 update_output_chunk(out, avail);
148 notify_via_evtchn(xen_start_info.store_evtchn);
149 } while (len != 0);
151 return 0;
152 }
154 int xs_input_avail(void)
155 {
156 unsigned int avail;
157 struct ringbuf_head *in = inbuf();
159 get_input_chunk(in, in->buf, &avail);
160 return avail != 0;
161 }
163 int xb_read(void *data, unsigned len)
164 {
165 struct ringbuf_head h;
166 struct ringbuf_head *in = inbuf();
167 int was_full;
169 while (len != 0) {
170 unsigned int avail;
171 const char *src;
173 wait_event(xb_waitq, xs_input_avail());
174 h = *in;
175 mb();
176 if (!check_buffer(&h)) {
177 set_current_state(TASK_RUNNING);
178 return -EIO;
179 }
181 src = get_input_chunk(&h, in->buf, &avail);
182 if (avail > len)
183 avail = len;
184 was_full = !output_avail(&h);
186 memcpy(data, src, avail);
187 data += avail;
188 len -= avail;
189 update_input_chunk(in, avail);
190 pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
191 /* If it was full, tell them we've taken some. */
192 if (was_full)
193 notify_via_evtchn(xen_start_info.store_evtchn);
194 }
196 /* If we left something, wake watch thread to deal with it. */
197 if (xs_input_avail())
198 wake_up(&xb_waitq);
200 return 0;
201 }
203 /* Set up interrupt handler off store event channel. */
204 int xb_init_comms(void)
205 {
206 int err;
208 if (!xen_start_info.store_evtchn)
209 return 0;
211 err = bind_evtchn_to_irqhandler(
212 xen_start_info.store_evtchn, wake_waiting,
213 0, "xenbus", &xb_waitq);
214 if (err) {
215 printk(KERN_ERR "XENBUS request irq failed %i\n", err);
216 unbind_evtchn_from_irq(xen_start_info.store_evtchn);
217 return err;
218 }
220 /* FIXME zero out page -- domain builder should probably do this*/
221 memset(mfn_to_virt(xen_start_info.store_mfn), 0, PAGE_SIZE);
223 return 0;
224 }
226 void xb_suspend_comms(void)
227 {
229 if (!xen_start_info.store_evtchn)
230 return;
232 unbind_evtchn_from_irqhandler(xen_start_info.store_evtchn, &xb_waitq);
233 }