mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 16:53:55 -06:00
hw/xen: Add xenstore operations to allow redirection to internal emulation
Signed-off-by: Paul Durrant <pdurrant@amazon.com> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> Reviewed-by: Paul Durrant <paul@xen.org>
This commit is contained in:
parent
15e283c5b6
commit
ba2a92db1f
18 changed files with 532 additions and 416 deletions
261
hw/xen/xen-bus.c
261
hw/xen/xen-bus.c
|
@ -62,7 +62,7 @@ static void xen_device_unplug(XenDevice *xendev, Error **errp)
|
|||
|
||||
/* Mimic the way the Xen toolstack does an unplug */
|
||||
again:
|
||||
tid = xs_transaction_start(xenbus->xsh);
|
||||
tid = qemu_xen_xs_transaction_start(xenbus->xsh);
|
||||
if (tid == XBT_NULL) {
|
||||
error_setg_errno(errp, errno, "failed xs_transaction_start");
|
||||
return;
|
||||
|
@ -80,7 +80,7 @@ again:
|
|||
goto abort;
|
||||
}
|
||||
|
||||
if (!xs_transaction_end(xenbus->xsh, tid, false)) {
|
||||
if (!qemu_xen_xs_transaction_end(xenbus->xsh, tid, false)) {
|
||||
if (errno == EAGAIN) {
|
||||
goto again;
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ abort:
|
|||
* We only abort if there is already a failure so ignore any error
|
||||
* from ending the transaction.
|
||||
*/
|
||||
xs_transaction_end(xenbus->xsh, tid, true);
|
||||
qemu_xen_xs_transaction_end(xenbus->xsh, tid, true);
|
||||
}
|
||||
|
||||
static void xen_bus_print_dev(Monitor *mon, DeviceState *dev, int indent)
|
||||
|
@ -111,143 +111,6 @@ static char *xen_bus_get_dev_path(DeviceState *dev)
|
|||
return xen_device_get_backend_path(XEN_DEVICE(dev));
|
||||
}
|
||||
|
||||
struct XenWatch {
|
||||
char *node, *key;
|
||||
char *token;
|
||||
XenWatchHandler handler;
|
||||
void *opaque;
|
||||
Notifier notifier;
|
||||
};
|
||||
|
||||
static void watch_notify(Notifier *n, void *data)
|
||||
{
|
||||
XenWatch *watch = container_of(n, XenWatch, notifier);
|
||||
const char *token = data;
|
||||
|
||||
if (!strcmp(watch->token, token)) {
|
||||
watch->handler(watch->opaque);
|
||||
}
|
||||
}
|
||||
|
||||
static XenWatch *new_watch(const char *node, const char *key,
|
||||
XenWatchHandler handler, void *opaque)
|
||||
{
|
||||
XenWatch *watch = g_new0(XenWatch, 1);
|
||||
QemuUUID uuid;
|
||||
|
||||
qemu_uuid_generate(&uuid);
|
||||
|
||||
watch->token = qemu_uuid_unparse_strdup(&uuid);
|
||||
watch->node = g_strdup(node);
|
||||
watch->key = g_strdup(key);
|
||||
watch->handler = handler;
|
||||
watch->opaque = opaque;
|
||||
watch->notifier.notify = watch_notify;
|
||||
|
||||
return watch;
|
||||
}
|
||||
|
||||
static void free_watch(XenWatch *watch)
|
||||
{
|
||||
g_free(watch->token);
|
||||
g_free(watch->key);
|
||||
g_free(watch->node);
|
||||
|
||||
g_free(watch);
|
||||
}
|
||||
|
||||
struct XenWatchList {
|
||||
struct xs_handle *xsh;
|
||||
NotifierList notifiers;
|
||||
};
|
||||
|
||||
static void watch_list_event(void *opaque)
|
||||
{
|
||||
XenWatchList *watch_list = opaque;
|
||||
char **v;
|
||||
const char *token;
|
||||
|
||||
v = xs_check_watch(watch_list->xsh);
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
|
||||
token = v[XS_WATCH_TOKEN];
|
||||
|
||||
notifier_list_notify(&watch_list->notifiers, (void *)token);
|
||||
|
||||
free(v);
|
||||
}
|
||||
|
||||
static XenWatchList *watch_list_create(struct xs_handle *xsh)
|
||||
{
|
||||
XenWatchList *watch_list = g_new0(XenWatchList, 1);
|
||||
|
||||
g_assert(xsh);
|
||||
|
||||
watch_list->xsh = xsh;
|
||||
notifier_list_init(&watch_list->notifiers);
|
||||
qemu_set_fd_handler(xs_fileno(watch_list->xsh), watch_list_event, NULL,
|
||||
watch_list);
|
||||
|
||||
return watch_list;
|
||||
}
|
||||
|
||||
static void watch_list_destroy(XenWatchList *watch_list)
|
||||
{
|
||||
g_assert(notifier_list_empty(&watch_list->notifiers));
|
||||
qemu_set_fd_handler(xs_fileno(watch_list->xsh), NULL, NULL, NULL);
|
||||
g_free(watch_list);
|
||||
}
|
||||
|
||||
static XenWatch *watch_list_add(XenWatchList *watch_list, const char *node,
|
||||
const char *key, XenWatchHandler handler,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
XenWatch *watch = new_watch(node, key, handler, opaque);
|
||||
|
||||
notifier_list_add(&watch_list->notifiers, &watch->notifier);
|
||||
|
||||
xs_node_watch(watch_list->xsh, node, key, watch->token, errp);
|
||||
if (*errp) {
|
||||
notifier_remove(&watch->notifier);
|
||||
free_watch(watch);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return watch;
|
||||
}
|
||||
|
||||
static void watch_list_remove(XenWatchList *watch_list, XenWatch *watch,
|
||||
Error **errp)
|
||||
{
|
||||
xs_node_unwatch(watch_list->xsh, watch->node, watch->key, watch->token,
|
||||
errp);
|
||||
|
||||
notifier_remove(&watch->notifier);
|
||||
free_watch(watch);
|
||||
}
|
||||
|
||||
static XenWatch *xen_bus_add_watch(XenBus *xenbus, const char *node,
|
||||
const char *key, XenWatchHandler handler,
|
||||
Error **errp)
|
||||
{
|
||||
trace_xen_bus_add_watch(node, key);
|
||||
|
||||
return watch_list_add(xenbus->watch_list, node, key, handler, xenbus,
|
||||
errp);
|
||||
}
|
||||
|
||||
static void xen_bus_remove_watch(XenBus *xenbus, XenWatch *watch,
|
||||
Error **errp)
|
||||
{
|
||||
trace_xen_bus_remove_watch(watch->node, watch->key);
|
||||
|
||||
watch_list_remove(xenbus->watch_list, watch, errp);
|
||||
}
|
||||
|
||||
static void xen_bus_backend_create(XenBus *xenbus, const char *type,
|
||||
const char *name, char *path,
|
||||
Error **errp)
|
||||
|
@ -261,15 +124,15 @@ static void xen_bus_backend_create(XenBus *xenbus, const char *type,
|
|||
trace_xen_bus_backend_create(type, path);
|
||||
|
||||
again:
|
||||
tid = xs_transaction_start(xenbus->xsh);
|
||||
tid = qemu_xen_xs_transaction_start(xenbus->xsh);
|
||||
if (tid == XBT_NULL) {
|
||||
error_setg(errp, "failed xs_transaction_start");
|
||||
return;
|
||||
}
|
||||
|
||||
key = xs_directory(xenbus->xsh, tid, path, &n);
|
||||
key = qemu_xen_xs_directory(xenbus->xsh, tid, path, &n);
|
||||
if (!key) {
|
||||
if (!xs_transaction_end(xenbus->xsh, tid, true)) {
|
||||
if (!qemu_xen_xs_transaction_end(xenbus->xsh, tid, true)) {
|
||||
error_setg_errno(errp, errno, "failed xs_transaction_end");
|
||||
}
|
||||
return;
|
||||
|
@ -300,7 +163,7 @@ again:
|
|||
|
||||
free(key);
|
||||
|
||||
if (!xs_transaction_end(xenbus->xsh, tid, false)) {
|
||||
if (!qemu_xen_xs_transaction_end(xenbus->xsh, tid, false)) {
|
||||
qobject_unref(opts);
|
||||
|
||||
if (errno == EAGAIN) {
|
||||
|
@ -327,7 +190,7 @@ static void xen_bus_type_enumerate(XenBus *xenbus, const char *type)
|
|||
|
||||
trace_xen_bus_type_enumerate(type);
|
||||
|
||||
backend = xs_directory(xenbus->xsh, XBT_NULL, domain_path, &n);
|
||||
backend = qemu_xen_xs_directory(xenbus->xsh, XBT_NULL, domain_path, &n);
|
||||
if (!backend) {
|
||||
goto out;
|
||||
}
|
||||
|
@ -372,7 +235,7 @@ static void xen_bus_enumerate(XenBus *xenbus)
|
|||
|
||||
trace_xen_bus_enumerate();
|
||||
|
||||
type = xs_directory(xenbus->xsh, XBT_NULL, "backend", &n);
|
||||
type = qemu_xen_xs_directory(xenbus->xsh, XBT_NULL, "backend", &n);
|
||||
if (!type) {
|
||||
return;
|
||||
}
|
||||
|
@ -415,7 +278,7 @@ static void xen_bus_cleanup(XenBus *xenbus)
|
|||
}
|
||||
}
|
||||
|
||||
static void xen_bus_backend_changed(void *opaque)
|
||||
static void xen_bus_backend_changed(void *opaque, const char *path)
|
||||
{
|
||||
XenBus *xenbus = opaque;
|
||||
|
||||
|
@ -434,7 +297,7 @@ static void xen_bus_unrealize(BusState *bus)
|
|||
|
||||
for (i = 0; i < xenbus->backend_types; i++) {
|
||||
if (xenbus->backend_watch[i]) {
|
||||
xen_bus_remove_watch(xenbus, xenbus->backend_watch[i], NULL);
|
||||
xs_node_unwatch(xenbus->xsh, xenbus->backend_watch[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -442,13 +305,8 @@ static void xen_bus_unrealize(BusState *bus)
|
|||
xenbus->backend_watch = NULL;
|
||||
}
|
||||
|
||||
if (xenbus->watch_list) {
|
||||
watch_list_destroy(xenbus->watch_list);
|
||||
xenbus->watch_list = NULL;
|
||||
}
|
||||
|
||||
if (xenbus->xsh) {
|
||||
xs_close(xenbus->xsh);
|
||||
qemu_xen_xs_close(xenbus->xsh);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -463,7 +321,7 @@ static void xen_bus_realize(BusState *bus, Error **errp)
|
|||
|
||||
trace_xen_bus_realize();
|
||||
|
||||
xenbus->xsh = xs_open(0);
|
||||
xenbus->xsh = qemu_xen_xs_open();
|
||||
if (!xenbus->xsh) {
|
||||
error_setg_errno(errp, errno, "failed xs_open");
|
||||
goto fail;
|
||||
|
@ -476,19 +334,18 @@ static void xen_bus_realize(BusState *bus, Error **errp)
|
|||
xenbus->backend_id = 0; /* Assume lack of node means dom0 */
|
||||
}
|
||||
|
||||
xenbus->watch_list = watch_list_create(xenbus->xsh);
|
||||
|
||||
module_call_init(MODULE_INIT_XEN_BACKEND);
|
||||
|
||||
type = xen_backend_get_types(&xenbus->backend_types);
|
||||
xenbus->backend_watch = g_new(XenWatch *, xenbus->backend_types);
|
||||
xenbus->backend_watch = g_new(struct qemu_xs_watch *,
|
||||
xenbus->backend_types);
|
||||
|
||||
for (i = 0; i < xenbus->backend_types; i++) {
|
||||
char *node = g_strdup_printf("backend/%s", type[i]);
|
||||
|
||||
xenbus->backend_watch[i] =
|
||||
xen_bus_add_watch(xenbus, node, key, xen_bus_backend_changed,
|
||||
&local_err);
|
||||
xs_node_watch(xenbus->xsh, node, key, xen_bus_backend_changed,
|
||||
xenbus, &local_err);
|
||||
if (local_err) {
|
||||
/* This need not be treated as a hard error so don't propagate */
|
||||
error_reportf_err(local_err,
|
||||
|
@ -631,7 +488,7 @@ static bool xen_device_frontend_is_active(XenDevice *xendev)
|
|||
}
|
||||
}
|
||||
|
||||
static void xen_device_backend_changed(void *opaque)
|
||||
static void xen_device_backend_changed(void *opaque, const char *path)
|
||||
{
|
||||
XenDevice *xendev = opaque;
|
||||
const char *type = object_get_typename(OBJECT(xendev));
|
||||
|
@ -685,66 +542,35 @@ static void xen_device_backend_changed(void *opaque)
|
|||
}
|
||||
}
|
||||
|
||||
static XenWatch *xen_device_add_watch(XenDevice *xendev, const char *node,
|
||||
const char *key,
|
||||
XenWatchHandler handler,
|
||||
Error **errp)
|
||||
{
|
||||
const char *type = object_get_typename(OBJECT(xendev));
|
||||
|
||||
trace_xen_device_add_watch(type, xendev->name, node, key);
|
||||
|
||||
return watch_list_add(xendev->watch_list, node, key, handler, xendev,
|
||||
errp);
|
||||
}
|
||||
|
||||
static void xen_device_remove_watch(XenDevice *xendev, XenWatch *watch,
|
||||
Error **errp)
|
||||
{
|
||||
const char *type = object_get_typename(OBJECT(xendev));
|
||||
|
||||
trace_xen_device_remove_watch(type, xendev->name, watch->node,
|
||||
watch->key);
|
||||
|
||||
watch_list_remove(xendev->watch_list, watch, errp);
|
||||
}
|
||||
|
||||
|
||||
static void xen_device_backend_create(XenDevice *xendev, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
|
||||
struct xs_permissions perms[2];
|
||||
|
||||
xendev->backend_path = xen_device_get_backend_path(xendev);
|
||||
|
||||
perms[0].id = xenbus->backend_id;
|
||||
perms[0].perms = XS_PERM_NONE;
|
||||
perms[1].id = xendev->frontend_id;
|
||||
perms[1].perms = XS_PERM_READ;
|
||||
|
||||
g_assert(xenbus->xsh);
|
||||
|
||||
xs_node_create(xenbus->xsh, XBT_NULL, xendev->backend_path, perms,
|
||||
ARRAY_SIZE(perms), errp);
|
||||
xs_node_create(xenbus->xsh, XBT_NULL, xendev->backend_path,
|
||||
xenbus->backend_id, xendev->frontend_id, XS_PERM_READ, errp);
|
||||
if (*errp) {
|
||||
error_prepend(errp, "failed to create backend: ");
|
||||
return;
|
||||
}
|
||||
|
||||
xendev->backend_state_watch =
|
||||
xen_device_add_watch(xendev, xendev->backend_path,
|
||||
"state", xen_device_backend_changed,
|
||||
errp);
|
||||
xs_node_watch(xendev->xsh, xendev->backend_path,
|
||||
"state", xen_device_backend_changed, xendev,
|
||||
errp);
|
||||
if (*errp) {
|
||||
error_prepend(errp, "failed to watch backend state: ");
|
||||
return;
|
||||
}
|
||||
|
||||
xendev->backend_online_watch =
|
||||
xen_device_add_watch(xendev, xendev->backend_path,
|
||||
"online", xen_device_backend_changed,
|
||||
errp);
|
||||
xs_node_watch(xendev->xsh, xendev->backend_path,
|
||||
"online", xen_device_backend_changed, xendev,
|
||||
errp);
|
||||
if (*errp) {
|
||||
error_prepend(errp, "failed to watch backend online: ");
|
||||
return;
|
||||
|
@ -757,12 +583,12 @@ static void xen_device_backend_destroy(XenDevice *xendev)
|
|||
Error *local_err = NULL;
|
||||
|
||||
if (xendev->backend_online_watch) {
|
||||
xen_device_remove_watch(xendev, xendev->backend_online_watch, NULL);
|
||||
xs_node_unwatch(xendev->xsh, xendev->backend_online_watch);
|
||||
xendev->backend_online_watch = NULL;
|
||||
}
|
||||
|
||||
if (xendev->backend_state_watch) {
|
||||
xen_device_remove_watch(xendev, xendev->backend_state_watch, NULL);
|
||||
xs_node_unwatch(xendev->xsh, xendev->backend_state_watch);
|
||||
xendev->backend_state_watch = NULL;
|
||||
}
|
||||
|
||||
|
@ -837,7 +663,7 @@ static void xen_device_frontend_set_state(XenDevice *xendev,
|
|||
}
|
||||
}
|
||||
|
||||
static void xen_device_frontend_changed(void *opaque)
|
||||
static void xen_device_frontend_changed(void *opaque, const char *path)
|
||||
{
|
||||
XenDevice *xendev = opaque;
|
||||
XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
|
||||
|
@ -885,7 +711,6 @@ static void xen_device_frontend_create(XenDevice *xendev, Error **errp)
|
|||
{
|
||||
ERRP_GUARD();
|
||||
XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
|
||||
struct xs_permissions perms[2];
|
||||
|
||||
xendev->frontend_path = xen_device_get_frontend_path(xendev);
|
||||
|
||||
|
@ -894,15 +719,11 @@ static void xen_device_frontend_create(XenDevice *xendev, Error **errp)
|
|||
* toolstack.
|
||||
*/
|
||||
if (!xen_device_frontend_exists(xendev)) {
|
||||
perms[0].id = xendev->frontend_id;
|
||||
perms[0].perms = XS_PERM_NONE;
|
||||
perms[1].id = xenbus->backend_id;
|
||||
perms[1].perms = XS_PERM_READ | XS_PERM_WRITE;
|
||||
|
||||
g_assert(xenbus->xsh);
|
||||
|
||||
xs_node_create(xenbus->xsh, XBT_NULL, xendev->frontend_path, perms,
|
||||
ARRAY_SIZE(perms), errp);
|
||||
xs_node_create(xenbus->xsh, XBT_NULL, xendev->frontend_path,
|
||||
xendev->frontend_id, xenbus->backend_id,
|
||||
XS_PERM_READ | XS_PERM_WRITE, errp);
|
||||
if (*errp) {
|
||||
error_prepend(errp, "failed to create frontend: ");
|
||||
return;
|
||||
|
@ -910,8 +731,8 @@ static void xen_device_frontend_create(XenDevice *xendev, Error **errp)
|
|||
}
|
||||
|
||||
xendev->frontend_state_watch =
|
||||
xen_device_add_watch(xendev, xendev->frontend_path, "state",
|
||||
xen_device_frontend_changed, errp);
|
||||
xs_node_watch(xendev->xsh, xendev->frontend_path, "state",
|
||||
xen_device_frontend_changed, xendev, errp);
|
||||
if (*errp) {
|
||||
error_prepend(errp, "failed to watch frontend state: ");
|
||||
}
|
||||
|
@ -923,8 +744,7 @@ static void xen_device_frontend_destroy(XenDevice *xendev)
|
|||
Error *local_err = NULL;
|
||||
|
||||
if (xendev->frontend_state_watch) {
|
||||
xen_device_remove_watch(xendev, xendev->frontend_state_watch,
|
||||
NULL);
|
||||
xs_node_unwatch(xendev->xsh, xendev->frontend_state_watch);
|
||||
xendev->frontend_state_watch = NULL;
|
||||
}
|
||||
|
||||
|
@ -1146,13 +966,8 @@ static void xen_device_unrealize(DeviceState *dev)
|
|||
xendev->xgth = NULL;
|
||||
}
|
||||
|
||||
if (xendev->watch_list) {
|
||||
watch_list_destroy(xendev->watch_list);
|
||||
xendev->watch_list = NULL;
|
||||
}
|
||||
|
||||
if (xendev->xsh) {
|
||||
xs_close(xendev->xsh);
|
||||
qemu_xen_xs_close(xendev->xsh);
|
||||
xendev->xsh = NULL;
|
||||
}
|
||||
|
||||
|
@ -1197,14 +1012,12 @@ static void xen_device_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
trace_xen_device_realize(type, xendev->name);
|
||||
|
||||
xendev->xsh = xs_open(0);
|
||||
xendev->xsh = qemu_xen_xs_open();
|
||||
if (!xendev->xsh) {
|
||||
error_setg_errno(errp, errno, "failed xs_open");
|
||||
goto unrealize;
|
||||
}
|
||||
|
||||
xendev->watch_list = watch_list_create(xendev->xsh);
|
||||
|
||||
xendev->xgth = qemu_xen_gnttab_open();
|
||||
if (!xendev->xgth) {
|
||||
error_setg_errno(errp, errno, "failed xengnttab_open");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue