[BACK]Return to xenbus_comms.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / xen / xenbus

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>