qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

xen_pvdev.c (8133B)


      1 /*
      2  * Xen para-virtualization device
      3  *
      4  *  (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Lesser General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2.1 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Lesser General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Lesser General Public
     17  * License along with this library; if not, see <http://www.gnu.org/licenses/>
     18  */
     19 
     20 #include "qemu/osdep.h"
     21 #include "qemu/log.h"
     22 #include "qemu/main-loop.h"
     23 #include "hw/qdev-core.h"
     24 #include "hw/xen/xen-legacy-backend.h"
     25 #include "hw/xen/xen_pvdev.h"
     26 
     27 /* private */
     28 static int debug;
     29 
     30 struct xs_dirs {
     31     char *xs_dir;
     32     QTAILQ_ENTRY(xs_dirs) list;
     33 };
     34 
     35 static QTAILQ_HEAD(, xs_dirs) xs_cleanup =
     36     QTAILQ_HEAD_INITIALIZER(xs_cleanup);
     37 
     38 static QTAILQ_HEAD(, XenLegacyDevice) xendevs =
     39     QTAILQ_HEAD_INITIALIZER(xendevs);
     40 
     41 /* ------------------------------------------------------------- */
     42 
     43 static void xenstore_cleanup_dir(char *dir)
     44 {
     45     struct xs_dirs *d;
     46 
     47     d = g_malloc(sizeof(*d));
     48     d->xs_dir = dir;
     49     QTAILQ_INSERT_TAIL(&xs_cleanup, d, list);
     50 }
     51 
     52 void xen_config_cleanup(void)
     53 {
     54     struct xs_dirs *d;
     55 
     56     QTAILQ_FOREACH(d, &xs_cleanup, list) {
     57         xs_rm(xenstore, 0, d->xs_dir);
     58     }
     59 }
     60 
     61 int xenstore_mkdir(char *path, int p)
     62 {
     63     struct xs_permissions perms[2] = {
     64         {
     65             .id    = 0, /* set owner: dom0 */
     66         }, {
     67             .id    = xen_domid,
     68             .perms = p,
     69         }
     70     };
     71 
     72     if (!xs_mkdir(xenstore, 0, path)) {
     73         xen_pv_printf(NULL, 0, "xs_mkdir %s: failed\n", path);
     74         return -1;
     75     }
     76     xenstore_cleanup_dir(g_strdup(path));
     77 
     78     if (!xs_set_permissions(xenstore, 0, path, perms, 2)) {
     79         xen_pv_printf(NULL, 0, "xs_set_permissions %s: failed\n", path);
     80         return -1;
     81     }
     82     return 0;
     83 }
     84 
     85 int xenstore_write_str(const char *base, const char *node, const char *val)
     86 {
     87     char abspath[XEN_BUFSIZE];
     88 
     89     snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
     90     if (!xs_write(xenstore, 0, abspath, val, strlen(val))) {
     91         return -1;
     92     }
     93     return 0;
     94 }
     95 
     96 char *xenstore_read_str(const char *base, const char *node)
     97 {
     98     char abspath[XEN_BUFSIZE];
     99     unsigned int len;
    100     char *str, *ret = NULL;
    101 
    102     snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
    103     str = xs_read(xenstore, 0, abspath, &len);
    104     if (str != NULL) {
    105         /* move to qemu-allocated memory to make sure
    106          * callers can savely g_free() stuff. */
    107         ret = g_strdup(str);
    108         free(str);
    109     }
    110     return ret;
    111 }
    112 
    113 int xenstore_write_int(const char *base, const char *node, int ival)
    114 {
    115     char val[12];
    116 
    117     snprintf(val, sizeof(val), "%d", ival);
    118     return xenstore_write_str(base, node, val);
    119 }
    120 
    121 int xenstore_write_int64(const char *base, const char *node, int64_t ival)
    122 {
    123     char val[21];
    124 
    125     snprintf(val, sizeof(val), "%"PRId64, ival);
    126     return xenstore_write_str(base, node, val);
    127 }
    128 
    129 int xenstore_read_int(const char *base, const char *node, int *ival)
    130 {
    131     char *val;
    132     int rc = -1;
    133 
    134     val = xenstore_read_str(base, node);
    135     if (val && 1 == sscanf(val, "%d", ival)) {
    136         rc = 0;
    137     }
    138     g_free(val);
    139     return rc;
    140 }
    141 
    142 int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval)
    143 {
    144     char *val;
    145     int rc = -1;
    146 
    147     val = xenstore_read_str(base, node);
    148     if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
    149         rc = 0;
    150     }
    151     g_free(val);
    152     return rc;
    153 }
    154 
    155 void xenstore_update(void *unused)
    156 {
    157     char **vec = NULL;
    158     intptr_t type, ops, ptr;
    159     unsigned int dom, count;
    160 
    161     vec = xs_read_watch(xenstore, &count);
    162     if (vec == NULL) {
    163         goto cleanup;
    164     }
    165 
    166     if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
    167                &type, &dom, &ops) == 3) {
    168         xenstore_update_be(vec[XS_WATCH_PATH], (void *)type, dom, (void*)ops);
    169     }
    170     if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
    171         xenstore_update_fe(vec[XS_WATCH_PATH], (void *)ptr);
    172     }
    173 
    174 cleanup:
    175     free(vec);
    176 }
    177 
    178 const char *xenbus_strstate(enum xenbus_state state)
    179 {
    180     static const char *const name[] = {
    181         [XenbusStateUnknown]       = "Unknown",
    182         [XenbusStateInitialising]  = "Initialising",
    183         [XenbusStateInitWait]      = "InitWait",
    184         [XenbusStateInitialised]   = "Initialised",
    185         [XenbusStateConnected]     = "Connected",
    186         [XenbusStateClosing]       = "Closing",
    187         [XenbusStateClosed]        = "Closed",
    188     };
    189     return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
    190 }
    191 
    192 /*
    193  * msg_level:
    194  *  0 == errors (stderr + logfile).
    195  *  1 == informative debug messages (logfile only).
    196  *  2 == noisy debug messages (logfile only).
    197  *  3 == will flood your log (logfile only).
    198  */
    199 static void xen_pv_output_msg(struct XenLegacyDevice *xendev,
    200                               FILE *f, const char *fmt, va_list args)
    201 {
    202     if (xendev) {
    203         fprintf(f, "xen be: %s: ", xendev->name);
    204     } else {
    205         fprintf(f, "xen be core: ");
    206     }
    207     vfprintf(f, fmt, args);
    208 }
    209 
    210 void xen_pv_printf(struct XenLegacyDevice *xendev, int msg_level,
    211                    const char *fmt, ...)
    212 {
    213     FILE *logfile;
    214     va_list args;
    215 
    216     if (msg_level > (xendev ? xendev->debug : debug)) {
    217         return;
    218     }
    219 
    220     logfile = qemu_log_trylock();
    221     if (logfile) {
    222         va_start(args, fmt);
    223         xen_pv_output_msg(xendev, logfile, fmt, args);
    224         va_end(args);
    225         qemu_log_unlock(logfile);
    226     }
    227 
    228     if (msg_level == 0) {
    229         va_start(args, fmt);
    230         xen_pv_output_msg(xendev, stderr, fmt, args);
    231         va_end(args);
    232     }
    233 }
    234 
    235 void xen_pv_evtchn_event(void *opaque)
    236 {
    237     struct XenLegacyDevice *xendev = opaque;
    238     evtchn_port_t port;
    239 
    240     port = xenevtchn_pending(xendev->evtchndev);
    241     if (port != xendev->local_port) {
    242         xen_pv_printf(xendev, 0,
    243                       "xenevtchn_pending returned %d (expected %d)\n",
    244                       port, xendev->local_port);
    245         return;
    246     }
    247     xenevtchn_unmask(xendev->evtchndev, port);
    248 
    249     if (xendev->ops->event) {
    250         xendev->ops->event(xendev);
    251     }
    252 }
    253 
    254 void xen_pv_unbind_evtchn(struct XenLegacyDevice *xendev)
    255 {
    256     if (xendev->local_port == -1) {
    257         return;
    258     }
    259     qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
    260     xenevtchn_unbind(xendev->evtchndev, xendev->local_port);
    261     xen_pv_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
    262     xendev->local_port = -1;
    263 }
    264 
    265 int xen_pv_send_notify(struct XenLegacyDevice *xendev)
    266 {
    267     return xenevtchn_notify(xendev->evtchndev, xendev->local_port);
    268 }
    269 
    270 /* ------------------------------------------------------------- */
    271 
    272 struct XenLegacyDevice *xen_pv_find_xendev(const char *type, int dom, int dev)
    273 {
    274     struct XenLegacyDevice *xendev;
    275 
    276     QTAILQ_FOREACH(xendev, &xendevs, next) {
    277         if (xendev->dom != dom) {
    278             continue;
    279         }
    280         if (xendev->dev != dev) {
    281             continue;
    282         }
    283         if (strcmp(xendev->type, type) != 0) {
    284             continue;
    285         }
    286         return xendev;
    287     }
    288     return NULL;
    289 }
    290 
    291 /*
    292  * release xen backend device.
    293  */
    294 void xen_pv_del_xendev(struct XenLegacyDevice *xendev)
    295 {
    296     if (xendev->ops->free) {
    297         xendev->ops->free(xendev);
    298     }
    299 
    300     if (xendev->fe) {
    301         char token[XEN_BUFSIZE];
    302         snprintf(token, sizeof(token), "fe:%p", xendev);
    303         xs_unwatch(xenstore, xendev->fe, token);
    304         g_free(xendev->fe);
    305     }
    306 
    307     if (xendev->evtchndev != NULL) {
    308         xenevtchn_close(xendev->evtchndev);
    309     }
    310     if (xendev->gnttabdev != NULL) {
    311         xengnttab_close(xendev->gnttabdev);
    312     }
    313 
    314     QTAILQ_REMOVE(&xendevs, xendev, next);
    315 
    316     qdev_unplug(&xendev->qdev, NULL);
    317 }
    318 
    319 void xen_pv_insert_xendev(struct XenLegacyDevice *xendev)
    320 {
    321     QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
    322 }