ia64/xen-unstable

view tools/xcs/ctrl_interface.c @ 3966:0b9ff7354a95

bitkeeper revision 1.1236.1.47 (4225ff68LvKUt73k78dKjnXxsnQt7A)

Fix tools build. Clean up barrier defs.
Signed-off-by: Jerone Young <jyoung5@us.ibm.com>
Signed-off-by: Keir Fraser <keir.fraser@cl.cam.ac.uk>
author kaf24@scramble.cl.cam.ac.uk
date Wed Mar 02 18:01:12 2005 +0000 (2005-03-02)
parents 0a4b76b6b5a0
children d174682dedf2 a13b9052d91d a01199a95070
line source
1 /* control_interface.c
2 *
3 * Interfaces to control message rings to VMs.
4 *
5 * Most of this is directly based on the original xu interface to python
6 * written by Keir Fraser.
7 *
8 * (c) 2004, Andrew Warfield
9 *
10 */
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/ioctl.h>
16 #include <sys/mman.h>
17 #include <errno.h>
18 #include "xcs.h"
20 static int xc_handle = -1;
22 /* Called at start-of-day when using the control channel interface. */
23 int ctrl_chan_init(void)
24 {
25 if ( (xc_handle = xc_interface_open()) == -1 )
26 {
27 DPRINTF("Could not open Xen control interface");
28 return -1;
29 }
31 return 0;
32 }
34 static control_if_t *map_control_interface(int fd, unsigned long pfn,
35 u32 dom)
36 {
37 char *vaddr = xc_map_foreign_range( fd, dom, PAGE_SIZE,
38 PROT_READ|PROT_WRITE, pfn );
39 if ( vaddr == NULL )
40 return NULL;
41 return (control_if_t *)(vaddr + 2048);
42 }
44 static void unmap_control_interface(int fd, control_if_t *c)
45 {
46 char *vaddr = (char *)c - 2048;
47 (void)munmap(vaddr, PAGE_SIZE);
48 }
50 int ctrl_chan_notify(control_channel_t *cc)
51 {
52 return xc_evtchn_send(xc_handle, cc->local_port);
53 }
55 int ctrl_chan_read_request(control_channel_t *cc, xcs_control_msg_t *dmsg)
56 {
57 control_msg_t *smsg;
58 RING_IDX c = cc->tx_ring.req_cons;
60 if ( !RING_HAS_UNCONSUMED_REQUESTS(CTRL_RING, &cc->tx_ring) )
61 {
62 DPRINTF("no request to read\n");
63 return -1;
64 }
66 rmb(); /* make sure we see the data associated with the request */
67 smsg = RING_GET_REQUEST(CTRL_RING, &cc->tx_ring, c);
68 memcpy(&dmsg->msg, smsg, sizeof(*smsg));
69 if ( dmsg->msg.length > sizeof(dmsg->msg.msg) )
70 dmsg->msg.length = sizeof(dmsg->msg.msg);
71 cc->tx_ring.req_cons++;
72 return 0;
73 }
75 int ctrl_chan_write_request(control_channel_t *cc,
76 xcs_control_msg_t *smsg)
77 {
78 control_msg_t *dmsg;
79 RING_IDX p = cc->rx_ring.req_prod_pvt;
81 if ( RING_FULL(CTRL_RING, &cc->rx_ring) )
82 {
83 DPRINTF("no space to write request");
84 return -ENOSPC;
85 }
87 dmsg = RING_GET_REQUEST(CTRL_RING, &cc->rx_ring, p);
88 memcpy(dmsg, &smsg->msg, sizeof(*dmsg));
90 wmb();
91 cc->rx_ring.req_prod_pvt++;
92 RING_PUSH_REQUESTS(CTRL_RING, &cc->rx_ring);
94 return 0;
95 }
97 int ctrl_chan_read_response(control_channel_t *cc, xcs_control_msg_t *dmsg)
98 {
99 control_msg_t *smsg;
100 RING_IDX c = cc->rx_ring.rsp_cons;
102 if ( !RING_HAS_UNCONSUMED_RESPONSES(CTRL_RING, &cc->rx_ring) )
103 {
104 DPRINTF("no response to read");
105 return -1;
106 }
108 rmb(); /* make sure we see the data associated with the request */
109 smsg = RING_GET_RESPONSE(CTRL_RING, &cc->rx_ring, c);
110 memcpy(&dmsg->msg, smsg, sizeof(*smsg));
111 if ( dmsg->msg.length > sizeof(dmsg->msg.msg) )
112 dmsg->msg.length = sizeof(dmsg->msg.msg);
113 cc->rx_ring.rsp_cons++;
114 return 0;
115 }
117 int ctrl_chan_write_response(control_channel_t *cc,
118 xcs_control_msg_t *smsg)
119 {
120 control_msg_t *dmsg;
121 RING_IDX p = cc->tx_ring.rsp_prod_pvt;
123 /* akw: if the ring is synchronous, you should never need this test! */
124 /* (but it was in the original code... ) */
125 if ( cc->tx_ring.req_cons == cc->tx_ring.rsp_prod_pvt )
126 {
127 DPRINTF("no space to write response");
128 return -ENOSPC;
129 }
131 dmsg = RING_GET_RESPONSE(CTRL_RING, &cc->tx_ring, p);
132 memcpy(dmsg, &smsg->msg, sizeof(*dmsg));
134 wmb();
135 cc->tx_ring.rsp_prod_pvt++;
136 RING_PUSH_RESPONSES(CTRL_RING, &cc->tx_ring);
138 return 0;
139 }
141 int ctrl_chan_request_to_read(control_channel_t *cc)
142 {
143 return (RING_HAS_UNCONSUMED_REQUESTS(CTRL_RING, &cc->tx_ring));
144 }
146 int ctrl_chan_space_to_write_request(control_channel_t *cc)
147 {
148 return (!(RING_FULL(CTRL_RING, &cc->rx_ring)));
149 }
151 int ctrl_chan_response_to_read(control_channel_t *cc)
152 {
153 return (RING_HAS_UNCONSUMED_RESPONSES(CTRL_RING, &cc->rx_ring));
154 }
156 int ctrl_chan_space_to_write_response(control_channel_t *cc)
157 {
158 /* again, there is something fishy here. */
159 return ( cc->tx_ring.req_cons != cc->tx_ring.rsp_prod_pvt );
160 }
162 int ctrl_chan_connect(control_channel_t *cc)
163 {
164 xc_dominfo_t info;
166 if ( cc->connected )
167 {
168 return 0;
169 }
171 if ( (xc_domain_getinfo(xc_handle, cc->remote_dom, 1, &info) != 1) ||
172 (info.domid != cc->remote_dom) )
173 {
174 DPRINTF("Failed to obtain domain status");
175 return -1;
176 }
178 cc->interface =
179 map_control_interface(xc_handle, info.shared_info_frame,
180 cc->remote_dom);
182 if ( cc->interface == NULL )
183 {
184 DPRINTF("Failed to map domain control interface");
185 return -1;
186 }
188 /* Synchronise ring indexes. */
189 BACK_RING_ATTACH(CTRL_RING, &cc->tx_ring, &cc->interface->tx_ring);
190 FRONT_RING_ATTACH(CTRL_RING, &cc->rx_ring, &cc->interface->rx_ring);
192 cc->connected = 1;
194 return 0;
195 }
197 void ctrl_chan_disconnect(control_channel_t *cc)
198 {
199 if ( cc->connected )
200 unmap_control_interface(xc_handle, cc->interface);
201 cc->connected = 0;
202 }
205 control_channel_t *ctrl_chan_new(u32 dom, int local_port, int remote_port)
206 {
207 control_channel_t *cc;
209 cc = (control_channel_t *)malloc(sizeof(control_channel_t));
210 if ( cc == NULL ) return NULL;
212 cc->connected = 0;
213 cc->remote_dom = dom;
215 if ( dom == 0 )
216 {
217 /*
218 * The control-interface event channel for DOM0 is already set up.
219 * We use an ioctl to discover the port at our end of the channel.
220 */
221 local_port = ioctl(xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN,
222 NULL);
223 remote_port = -1; /* We don't need the remote end of the DOM0 link. */
224 if ( local_port < 0 )
225 {
226 DPRINTF("Could not open channel to DOM0");
227 goto fail;
228 }
229 }
230 else if ( xc_evtchn_bind_interdomain(xc_handle,
231 DOMID_SELF, dom,
232 &local_port, &remote_port) != 0 )
233 {
234 DPRINTF("Could not open channel to domain");
235 goto fail;
236 }
238 cc->local_port = local_port;
239 cc->remote_port = remote_port;
241 if ( ctrl_chan_connect(cc) != 0 )
242 goto fail;
244 return cc;
246 fail:
247 if ( dom != 0 )
248 (void)xc_evtchn_close(xc_handle, DOMID_SELF, local_port);
250 free(cc);
252 return NULL;
253 }
255 void ctrl_chan_free(control_channel_t *cc)
256 {
257 ctrl_chan_disconnect(cc);
258 if ( cc->remote_dom != 0 )
259 (void)xc_evtchn_close(xc_handle, DOMID_SELF, cc->local_port);
260 free(cc);
261 }
264 /* other libxc commands: */
266 int ctrl_chan_bind_virq(int virq, int *port)
267 {
268 return xc_evtchn_bind_virq(xc_handle, virq, port);
269 }