Annotation of src/sys/arch/xen/xenbus/xenbus_comms.c, Revision 1.24
1.24 ! jdolecek 1: /* $NetBSD: xenbus_comms.c,v 1.23 2020/05/06 16:50:13 bouyer Exp $ */
1.1 bouyer 2: /******************************************************************************
3: * xenbus_comms.c
4: *
5: * Low level code to talks to Xen Store: ringbuffer and event channel.
6: *
7: * Copyright (C) 2005 Rusty Russell, IBM Corporation
8: *
9: * This file may be distributed separately from the Linux kernel, or
10: * incorporated into other software packages, subject to the following license:
11: *
12: * Permission is hereby granted, free of charge, to any person obtaining a copy
13: * of this source file (the "Software"), to deal in the Software without
14: * restriction, including without limitation the rights to use, copy, modify,
15: * merge, publish, distribute, sublicense, and/or sell copies of the Software,
16: * and to permit persons to whom the Software is furnished to do so, subject to
17: * the following conditions:
18: *
19: * The above copyright notice and this permission notice shall be included in
20: * all copies or substantial portions of the Software.
21: *
22: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28: * IN THE SOFTWARE.
29: */
30:
1.2 bouyer 31: #include <sys/cdefs.h>
1.24 ! jdolecek 32: __KERNEL_RCSID(0, "$NetBSD: xenbus_comms.c,v 1.23 2020/05/06 16:50:13 bouyer Exp $");
1.2 bouyer 33:
34: #include <sys/types.h>
35: #include <sys/null.h>
36: #include <sys/errno.h>
37: #include <sys/param.h>
38: #include <sys/proc.h>
39: #include <sys/systm.h>
1.23 bouyer 40: #include <sys/mutex.h>
1.2 bouyer 41:
1.10 cegger 42: #include <xen/xen.h> /* for xendomain_is_dom0() */
1.22 bouyer 43: #include <xen/intr.h> /* for xendomain_is_dom0() */
1.5 bouyer 44: #include <xen/hypervisor.h>
45: #include <xen/evtchn.h>
46: #include <xen/xenbus.h>
1.1 bouyer 47: #include "xenbus_comms.h"
48:
1.2 bouyer 49: #undef XENDEBUG
50: #ifdef XENDEBUG
51: #define XENPRINTF(x) printf x
52: #else
53: #define XENPRINTF(x)
54: #endif
55:
1.16 cherry 56: static struct intrhand *ih;
1.2 bouyer 57: struct xenstore_domain_interface *xenstore_interface;
1.23 bouyer 58: static kmutex_t xenstore_lock;
59: static kcondvar_t xenstore_cv;
1.2 bouyer 60:
1.15 msaitoh 61: extern int xenstored_ready;
1.2 bouyer 62: // static DECLARE_WORK(probe_work, xenbus_probe, NULL);
63:
64: static int wake_waiting(void *);
65: static int check_indexes(XENSTORE_RING_IDX, XENSTORE_RING_IDX);
1.4 christos 66: static void *get_output_chunk(XENSTORE_RING_IDX, XENSTORE_RING_IDX,
1.2 bouyer 67: char *, uint32_t *);
1.4 christos 68: static const void *get_input_chunk(XENSTORE_RING_IDX, XENSTORE_RING_IDX,
1.2 bouyer 69: const char *, uint32_t *);
1.1 bouyer 70:
71:
1.2 bouyer 72: static inline struct xenstore_domain_interface *
73: xenstore_domain_interface(void)
1.1 bouyer 74: {
1.2 bouyer 75: return xenstore_interface;
1.1 bouyer 76: }
77:
1.2 bouyer 78: static int
79: wake_waiting(void *arg)
1.1 bouyer 80: {
1.8 cegger 81: if (__predict_false(xenstored_ready == 0 && xendomain_is_dom0())) {
1.23 bouyer 82: xb_xenstored_make_ready();
1.1 bouyer 83: }
84:
1.23 bouyer 85: mutex_enter(&xenstore_lock);
86: cv_broadcast(&xenstore_cv);
87: mutex_exit(&xenstore_lock);
1.2 bouyer 88: return 1;
1.1 bouyer 89: }
90:
1.2 bouyer 91: static int
92: check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
1.1 bouyer 93: {
94: return ((prod - cons) <= XENSTORE_RING_SIZE);
95: }
96:
1.2 bouyer 97: static void *
98: get_output_chunk(XENSTORE_RING_IDX cons,
1.1 bouyer 99: XENSTORE_RING_IDX prod,
100: char *buf, uint32_t *len)
101: {
102: *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
103: if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
104: *len = XENSTORE_RING_SIZE - (prod - cons);
105: return buf + MASK_XENSTORE_IDX(prod);
106: }
107:
1.2 bouyer 108: static const void *
109: get_input_chunk(XENSTORE_RING_IDX cons,
1.1 bouyer 110: XENSTORE_RING_IDX prod,
111: const char *buf, uint32_t *len)
112: {
113: *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
114: if ((prod - cons) < *len)
115: *len = prod - cons;
116: return buf + MASK_XENSTORE_IDX(cons);
117: }
118:
1.2 bouyer 119: int
120: xb_write(const void *data, unsigned len)
1.1 bouyer 121: {
122: struct xenstore_domain_interface *intf = xenstore_domain_interface();
123: XENSTORE_RING_IDX cons, prod;
124:
1.23 bouyer 125: mutex_enter(&xenstore_lock);
1.1 bouyer 126: while (len != 0) {
127: void *dst;
128: unsigned int avail;
129:
1.2 bouyer 130: while ((intf->req_prod - intf->req_cons) == XENSTORE_RING_SIZE) {
1.23 bouyer 131: XENPRINTF(("xb_write cv_wait\n"));
132: cv_wait(&xenstore_cv, &xenstore_lock);
133: XENPRINTF(("xb_write cv_wait done\n"));
1.2 bouyer 134: }
1.1 bouyer 135:
136: /* Read indexes, then verify. */
137: cons = intf->req_cons;
138: prod = intf->req_prod;
1.12 jym 139: xen_rmb();
1.2 bouyer 140: if (!check_indexes(cons, prod)) {
1.23 bouyer 141: mutex_exit(&xenstore_lock);
1.2 bouyer 142: return EIO;
143: }
1.1 bouyer 144:
145: dst = get_output_chunk(cons, prod, intf->req, &avail);
146: if (avail == 0)
147: continue;
148: if (avail > len)
149: avail = len;
150:
151: memcpy(dst, data, avail);
1.2 bouyer 152: data = (const char *)data + avail;
1.1 bouyer 153: len -= avail;
154:
155: /* Other side must not see new header until data is there. */
1.12 jym 156: xen_rmb();
1.1 bouyer 157: intf->req_prod += avail;
1.12 jym 158: xen_rmb();
1.1 bouyer 159:
1.2 bouyer 160: hypervisor_notify_via_evtchn(xen_start_info.store_evtchn);
1.1 bouyer 161: }
1.23 bouyer 162: mutex_exit(&xenstore_lock);
1.1 bouyer 163: return 0;
164: }
165:
1.2 bouyer 166: int
167: xb_read(void *data, unsigned len)
1.1 bouyer 168: {
169: struct xenstore_domain_interface *intf = xenstore_domain_interface();
170: XENSTORE_RING_IDX cons, prod;
171:
1.23 bouyer 172: mutex_enter(&xenstore_lock);
1.2 bouyer 173:
1.1 bouyer 174: while (len != 0) {
175: unsigned int avail;
176: const char *src;
177:
1.2 bouyer 178: while (intf->rsp_cons == intf->rsp_prod)
1.23 bouyer 179: cv_wait(&xenstore_cv, &xenstore_lock);
1.1 bouyer 180:
181: /* Read indexes, then verify. */
182: cons = intf->rsp_cons;
183: prod = intf->rsp_prod;
1.12 jym 184: xen_rmb();
1.2 bouyer 185: if (!check_indexes(cons, prod)) {
186: XENPRINTF(("xb_read EIO\n"));
1.23 bouyer 187: mutex_exit(&xenstore_lock);
1.2 bouyer 188: return EIO;
189: }
1.1 bouyer 190:
191: src = get_input_chunk(cons, prod, intf->rsp, &avail);
192: if (avail == 0)
193: continue;
194: if (avail > len)
195: avail = len;
196:
197: /* We must read header before we read data. */
1.12 jym 198: xen_rmb();
1.1 bouyer 199:
200: memcpy(data, src, avail);
1.2 bouyer 201: data = (char *)data + avail;
1.1 bouyer 202: len -= avail;
203:
204: /* Other side must not see free space until we've copied out */
1.12 jym 205: xen_rmb();
1.1 bouyer 206: intf->rsp_cons += avail;
1.12 jym 207: xen_rmb();
1.1 bouyer 208:
1.2 bouyer 209: XENPRINTF(("Finished read of %i bytes (%i to go)\n",
210: avail, len));
1.1 bouyer 211:
1.2 bouyer 212: hypervisor_notify_via_evtchn(xen_start_info.store_evtchn);
1.1 bouyer 213: }
1.23 bouyer 214: mutex_exit(&xenstore_lock);
1.1 bouyer 215: return 0;
216: }
217:
1.9 jym 218: /* Set up interrupt handler of store event channel. */
1.2 bouyer 219: int
1.7 cegger 220: xb_init_comms(device_t dev)
1.1 bouyer 221: {
1.23 bouyer 222: mutex_init(&xenstore_lock, MUTEX_DEFAULT, IPL_TTY);
223: cv_init(&xenstore_cv, "xsio");
224:
1.24 ! jdolecek 225: return xb_resume_comms(dev);
! 226: }
! 227:
! 228: int
! 229: xb_resume_comms(device_t dev)
! 230: {
! 231: int evtchn;
! 232:
1.14 jym 233: evtchn = xen_start_info.store_evtchn;
1.1 bouyer 234:
1.21 cherry 235: ih = xen_intr_establish_xname(-1, &xen_pic, evtchn, IST_LEVEL, IPL_TTY,
1.23 bouyer 236: wake_waiting, NULL, true, device_xname(dev));
1.16 cherry 237:
1.20 cherry 238: hypervisor_unmask_event(evtchn);
1.14 jym 239: aprint_verbose_dev(dev, "using event channel %d\n", evtchn);
1.13 jym 240:
1.1 bouyer 241: return 0;
242: }
243:
1.14 jym 244: void
245: xb_suspend_comms(device_t dev)
246: {
247: int evtchn;
248:
249: evtchn = xen_start_info.store_evtchn;
250:
251: hypervisor_mask_event(evtchn);
1.21 cherry 252: xen_intr_disestablish(ih);
1.14 jym 253: aprint_verbose_dev(dev, "removed event channel %d\n", evtchn);
254: }
255:
1.1 bouyer 256: /*
257: * Local variables:
258: * c-file-style: "linux"
259: * indent-tabs-mode: t
260: * c-indent-level: 8
261: * c-basic-offset: 8
262: * tab-width: 8
263: * End:
264: */
CVSweb <webmaster@jp.NetBSD.org>