]> xenbits.xensource.com Git - people/pauldu/qemu.git/commitdiff
hw/xen: Add stubs for XenStore backend implementation
authorDavid Woodhouse <dwmw@amazon.co.uk>
Thu, 19 Jan 2023 00:04:31 +0000 (00:04 +0000)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Fri, 20 Jan 2023 12:28:53 +0000 (12:28 +0000)
We can actually initiaize xenbus now too; it's unhappy that everything
(except xs_open) fails, but at least it doesn't abort. OTOH, we *might*
not want to just yet, since we might start to see other failure modes
when we exercise my completely untested grant table code and other
stuff :)

We can probably implement serialize/deserialize by letting me worry about
that in the xen_xenstore.c side and just calling an impl function to
populate or consume a GByteArray. It can hand you the list of pending
(already fired, not yet delivered) watch events too, or append them after.

./build/qemu-system-x86_64 -serial mon:stdio -M pc -display none \
-accel kvm,xen-version=0x4000a,kernel-irqchip=split -cpu host \
-m 1G -smp 2 -kernel bzImage \
-append "console=ttyS0 root=/dev/sda1 xen_emul_unplug=never" \
-drive file=/var/lib/libvirt/images/fedora28.qcow2,if=none,id=disk \
-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 \
--trace 'xenstore*' -nic user,model=e1000e

You can probably ditch the -kernel and -append if your disk image is set
up for serial bootloader and console. Or if you want to drop -display none
and actually deal with windows popping up :)

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
hw/i386/kvm/xen_xenstore.c
hw/i386/kvm/xenstore_impl.c
hw/i386/kvm/xenstore_impl.h
hw/i386/pc_piix.c

index ec9e7db0fc8e163e4cbaedf55945b53765389b9f..7445da0efd82f5b23c920ca67bec8e207d8cb3a5 100644 (file)
@@ -74,6 +74,8 @@ struct XenXenstoreState *xen_xenstore_singleton;
 static void xen_xenstore_event(void *opaque);
 static void fire_watch_cb(void *opaque, const char *path, const char *token);
 
+static struct xenstore_backend_ops emu_xenstore_backend_ops;
+
 static void xen_xenstore_realize(DeviceState *dev, Error **errp)
 {
     XenXenstoreState *s = XEN_XENSTORE(dev);
@@ -100,6 +102,7 @@ static void xen_xenstore_realize(DeviceState *dev, Error **errp)
                        xen_xenstore_event, NULL, NULL, NULL, s);
 
     s->impl = xs_impl_create();
+    xen_xenstore_ops = &emu_xenstore_backend_ops;
 }
 
 static bool xen_xenstore_is_needed(void *opaque)
@@ -1198,3 +1201,204 @@ int xen_xenstore_reset(void)
 
     return 0;
 }
+
+struct qemu_xs_handle {
+    XenstoreImplState *impl;
+};
+
+static struct qemu_xs_handle *xs_be_open(void)
+{
+    XenXenstoreState *s = xen_xenstore_singleton;
+    struct qemu_xs_handle *h;
+
+    if (!s && !s->impl) {
+        errno = -ENOSYS;
+        return NULL;
+    }
+
+    h= g_new0(struct qemu_xs_handle, 1);
+    h->impl = s->impl;
+
+    return h;
+}
+
+static void xs_be_close(struct qemu_xs_handle *h)
+{
+    g_free(h);
+}
+
+static char *xs_be_get_domain_path(struct qemu_xs_handle *h, unsigned int domid)
+{
+    return g_strdup_printf("/local/domain/%u", domid);
+}
+
+static char **xs_be_directory(struct qemu_xs_handle *h, xs_transaction_t t,
+                              const char *path, unsigned int *num)
+{
+    GList *items = NULL, *l;
+    unsigned int i = 0;
+    char **items_ret;
+    int err;
+
+    err = xs_impl_directory(h->impl, DOMID_QEMU, t, path, &items);
+    if (err) {
+        errno = err;
+        return NULL;
+    }
+
+    items_ret = g_new0(char *, g_list_length(items) + 1);
+
+    for (l = items; l; l = l->next) {
+        items_ret[i++] = l->data;
+    }
+    g_list_free(items);
+    return items_ret;
+}
+
+static void *xs_be_read(struct qemu_xs_handle *h, xs_transaction_t t,
+                        const char *path, unsigned int *len)
+{
+    GByteArray *data = g_byte_array_new();
+    bool free_segment = false;
+    int err;
+
+    err = xs_impl_read(h->impl, DOMID_QEMU, t, path, data);
+    if (err) {
+        free_segment = true;
+        errno = err;
+    }
+    return g_byte_array_free(data, free_segment);
+}
+
+static bool xs_be_write(struct qemu_xs_handle *h, xs_transaction_t t,
+                        const char *path, const void *data, unsigned int len)
+{
+    GByteArray *gdata = g_byte_array_new();
+    int err;
+
+    g_byte_array_append(gdata, data, len);
+    err = xs_impl_write(h->impl, DOMID_QEMU, t, path, gdata);
+    g_byte_array_free(gdata, true);
+    if (err) {
+        errno = err;
+        return false;
+    }
+    return true;
+}
+
+static bool xs_be_create(struct qemu_xs_handle *h, xs_transaction_t t,
+                         unsigned int owner, unsigned int domid,
+                         unsigned int perms, const char *path)
+{
+    g_autoptr(GByteArray) data = g_byte_array_new();
+    GList *perms_list = NULL;
+    int err;
+
+    /* mkdir does this */
+    err = xs_impl_read(h->impl, DOMID_QEMU, t, path, data);
+    if (err == ENOENT)
+        err = xs_impl_write(h->impl, DOMID_QEMU, t, path, data);
+    if (err) {
+        errno = err;
+        return false;
+    }
+
+    perms_list = g_list_append(perms_list,
+                               xs_perm_as_string(XS_PERM_NONE, owner));
+    perms_list = g_list_append(perms_list,
+                               xs_perm_as_string(perms, domid));
+
+    err = xs_impl_set_perms(h->impl, DOMID_QEMU, t, path, perms_list);
+    g_list_free_full(perms_list, g_free);
+    if (err) {
+        errno = err;
+        return false;
+    }
+    return true;
+}
+
+static bool xs_be_destroy(struct qemu_xs_handle *h, xs_transaction_t t,
+                          const char *path)
+{
+    int err = xs_impl_rm(h->impl, DOMID_QEMU, t, path);
+    if (err) {
+        errno = err;
+        return false;
+    }
+    return true;
+}
+
+struct qemu_xs_watch {
+    char *path;
+    xs_watch_fn fn;
+    void *opaque;
+};
+
+static void xs_be_watch_cb(void *opaque, const char *path, const char *token)
+{
+    struct qemu_xs_watch *w = opaque;
+
+    w->fn(w->opaque, w->path);
+}
+
+static struct qemu_xs_watch *xs_be_watch(struct qemu_xs_handle *h,
+                                         const char *path, xs_watch_fn fn,
+                                         void *opaque)
+{
+    struct qemu_xs_watch *w = g_new0(struct qemu_xs_watch, 1);
+    int err;
+
+    err = xs_impl_watch(h->impl, DOMID_QEMU, path, NULL, xs_be_watch_cb, w);
+    if (w) {
+        errno = err;
+        g_free(w);
+        return NULL;
+    }
+
+    w->path = g_strdup(path);
+    return w;
+}
+
+static void xs_be_unwatch(struct qemu_xs_handle *h, struct qemu_xs_watch *w)
+{
+    xs_impl_unwatch(h->impl, DOMID_QEMU, w->path, NULL, xs_be_watch_cb, w);
+    g_free(w->path);
+    g_free(w);
+}
+
+static xs_transaction_t xs_be_transaction_start(struct qemu_xs_handle *h)
+{
+    unsigned int new_tx = XBT_NULL;
+    int err = xs_impl_transaction_start(h->impl, DOMID_QEMU, XBT_NULL, &new_tx);
+    if (err) {
+        errno = err;
+        return XBT_NULL;
+    }
+    return new_tx;
+}
+
+static bool xs_be_transaction_end(struct qemu_xs_handle *h, xs_transaction_t t,
+                                  bool abort)
+{
+    int err = xs_impl_transaction_end(h->impl, DOMID_QEMU, t, !abort);
+    if (err) {
+        errno = err;
+        return false;
+    }
+    return true;
+}
+
+static struct xenstore_backend_ops emu_xenstore_backend_ops = {
+    .open = xs_be_open,
+    .close = xs_be_close,
+    .get_domain_path = xs_be_get_domain_path,
+    .directory = xs_be_directory,
+    .read = xs_be_read,
+    .write = xs_be_write,
+    .create = xs_be_create,
+    .destroy = xs_be_destroy,
+    .watch = xs_be_watch,
+    .unwatch = xs_be_unwatch,
+    .transaction_start = xs_be_transaction_start,
+    .transaction_end = xs_be_transaction_end,
+};
index f6d68d5ee654b6011f67375b1f371cd4f6da19a5..df51fd726a56ebb87ceed5a1cec604306e4ac665 100644 (file)
 
 #include "xen_xenstore.h"
 #include "xenstore_impl.h"
+#include "include/hw/xen/xen_backend_ops.h"
 
 struct XenstoreImplState {
 };
 
+char *xs_perm_as_string(unsigned int perm, unsigned int domid)
+{
+    char letter;
+
+    switch(perm) {
+    case XS_PERM_READ|XS_PERM_WRITE:
+        letter = 'b';
+        break;
+    case XS_PERM_READ:
+        letter = 'r';
+        break;
+    case XS_PERM_WRITE:
+        letter = 'w';
+        break;
+    case XS_PERM_NONE:
+    default:
+        letter = 'n';
+        break;
+    }
+
+    return g_strdup_printf("%c%u", letter, domid);
+}
+
 int xs_impl_read(XenstoreImplState *s, unsigned int dom_id, unsigned int tx_id,
                  const char *path, GByteArray *data)
 {
@@ -110,7 +134,9 @@ int xs_impl_reset_watches(XenstoreImplState *s, unsigned int dom_id)
     return ENOSYS;
 }
 
+
 XenstoreImplState *xs_impl_create(void)
 {
     return g_new0(XenstoreImplState, 1);
 }
+
index 40e305088636e3250eddbf1ba0814be094f0be1f..44aac532161e27ab53fd9206f420b9b997da4c01 100644 (file)
@@ -18,6 +18,8 @@ typedef struct XenstoreImplState XenstoreImplState;
 
 XenstoreImplState *xs_impl_create(void);
 
+char *xs_perm_as_string(unsigned int perm, unsigned int domid);
+
 /*
  * These functions return *positive* error numbers. This is a little
  * unconventional but it helps to keep us honest because there is
index c85950bc6d9cc5187fc40286aa048eb98f69f1ec..02a3f0eaf5378cc76916f04495aa19774dfb42b3 100644 (file)
@@ -175,7 +175,7 @@ static void pc_init1(MachineState *machine,
     }
 
 #ifdef CONFIG_XEN_BUS
-    if (xen_mode == XEN_ATTACH) {
+    if (xen_mode != XEN_DISABLED) {
         /* Initialize backend core & drivers */
         xen_bus_init();