/****************************************************************************** * Talks to Xen Store to figure out what devices we have. * * Copyright (C) 2005 Rusty Russell, IBM Corporation * Copyright (C) 2005 Mike Wray, Hewlett-Packard * Copyright (C) 2005, 2006 XenSource Ltd * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation; or, when distributed * separately from the Linux kernel or incorporated into other * software packages, subject to the following license: * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this source file (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE.
*/
/* Protect us against watches firing on old details when the otherend
details change, say immediately after a resume. */ if (!dev->otherend ||
strncmp(dev->otherend, path, strlen(dev->otherend))) {
dev_dbg(&dev->dev, "Ignoring watch at %s\n", path); return;
}
state = xenbus_read_driver_state(dev->otherend);
dev_dbg(&dev->dev, "state is %d, (%s), %s, %s\n",
state, xenbus_strstate(state), dev->otherend_watch.node, path);
/* * Ignore xenbus transitions during shutdown. This prevents us doing * work that can fail e.g., when the rootfs is gone.
*/ if (system_state > SYSTEM_RUNNING) { if (ignore_on_shutdown && (state == XenbusStateClosing))
xenbus_frontend_closed(dev); return;
}
if (drv->otherend_changed)
drv->otherend_changed(dev, state);
}
EXPORT_SYMBOL_GPL(xenbus_otherend_changed);
if (drv->remove) {
down(&dev->reclaim_sem);
drv->remove(dev);
up(&dev->reclaim_sem);
}
module_put(drv->driver.owner);
free_otherend_details(dev);
/* * If the toolstack has forced the device state to closing then set * the state to closed now to allow it to be cleaned up. * Similarly, if the driver does not support re-bind, set the * closed.
*/ if (!drv->allow_rebind ||
xenbus_read_driver_state(dev->nodename) == XenbusStateClosing)
xenbus_switch_state(dev, XenbusStateClosed);
}
EXPORT_SYMBOL_GPL(xenbus_dev_remove);
/* Match the info->nodename path, or any subdirectory of that path. */ if (strncmp(xendev->nodename, info->nodename, len)) return 0;
/* If the node name is longer, ensure it really is a subdirectory. */ if ((strlen(xendev->nodename) > len) && (xendev->nodename[len] != '/')) return 0;
int xenbus_probe_node(struct xen_bus_type *bus, constchar *type, constchar *nodename)
{ char devname[XEN_BUS_ID_SIZE]; int err; struct xenbus_device *xendev;
size_t stringlen; char *tmpstring;
enum xenbus_state state = xenbus_read_driver_state(nodename);
if (state != XenbusStateInitialising) { /* Device is not new, so ignore it. This can happen if a
device is going away after switching to Closed. */ return 0;
}
if (!xen_store_interface)
xen_store_interface = memremap(xen_store_gfn << XEN_PAGE_SHIFT,
XEN_PAGE_SIZE, MEMREMAP_WB); /* * Now it is safe to free the IRQ used for xenstore late * initialization. No need to unbind: it is about to be * bound again from xb_init_comms. Note that calling * unbind_from_irqhandler now would result in xen_evtchn_close() * being called and the event channel not being enabled again * afterwards, resulting in missed event notifications.
*/ if (xs_init_irq >= 0)
free_irq(xs_init_irq, &xb_waitq);
/* * In the HVM case, xenbus_init() deferred its call to * xs_init() in case callbacks were not operational yet. * So do it now.
*/ if (xen_store_domain_type == XS_HVM)
xs_init();
/* Notify others that xenstore is up */
blocking_notifier_call_chain(&xenstore_chain, 0, NULL);
}
/* * Returns true when XenStore init must be deferred in order to * allow the PCI platform device to be initialised, before we * can actually have event channel interrupts working.
*/ staticbool xs_hvm_defer_init_for_callback(void)
{ #ifdef CONFIG_XEN_PVHVM return xen_store_domain_type == XS_HVM &&
!xen_have_vector_callback; #else returnfalse; #endif
}
/* * We actually just want to wait for *any* trigger of xb_waitq, * and run xenbus_probe() the moment it occurs.
*/
prepare_to_wait(&xb_waitq, &w, TASK_INTERRUPTIBLE);
schedule();
finish_wait(&xb_waitq, &w);
DPRINTK("probing");
xenbus_probe(); return 0;
}
staticint __init xenbus_probe_initcall(void)
{ if (!xen_domain()) return -ENODEV;
/* * Probe XenBus here in the XS_PV case, and also XS_HVM unless we * need to wait for the platform PCI device to come up or * xen_store_interface is not ready.
*/ if (xen_store_domain_type == XS_PV ||
(xen_store_domain_type == XS_HVM &&
!xs_hvm_defer_init_for_callback() &&
XS_INTERFACE_READY))
xenbus_probe();
/* * For XS_LOCAL or when xen_store_interface is not ready, spawn a * thread which will wait for xenstored or a xenstore-stubdom to be * started, then probe. It will be triggered when communication * starts happening, by waiting on xb_waitq.
*/ if (xen_store_domain_type == XS_LOCAL || !XS_INTERFACE_READY) { struct task_struct *probe_task;
ret = HYPERVISOR_hvm_op(HVMOP_set_param, &a); if (ret) return ret;
/* * If xenbus_probe_initcall() deferred the xenbus_probe() * due to the callback not functioning yet, we can do it now.
*/ if (!xenstored_ready && xs_hvm_defer_init_for_callback())
xenbus_probe();
/* Set up event channel for xenstored which is run as a local process * (this is normally used only in dom0)
*/ staticint __init xenstored_local_init(void)
{ int err = -ENOMEM; unsignedlong page = 0; struct evtchn_alloc_unbound alloc_unbound;
staticint __init xenbus_init(void)
{ int err;
uint64_t v = 0; bool wait = false;
xen_store_domain_type = XS_UNKNOWN;
if (!xen_domain()) return -ENODEV;
xenbus_ring_ops_init();
if (xen_pv_domain())
xen_store_domain_type = XS_PV; if (xen_hvm_domain())
{
xen_store_domain_type = XS_HVM;
err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); if (err) goto out_error;
xen_store_evtchn = (int)v; if (!v && xen_initial_domain())
xen_store_domain_type = XS_LOCAL;
} if (xen_pv_domain() && !xen_start_info->store_evtchn)
xen_store_domain_type = XS_LOCAL; if (xen_pv_domain() && xen_start_info->store_evtchn)
xenstored_ready = 1;
switch (xen_store_domain_type) { case XS_LOCAL:
err = xenstored_local_init(); if (err) goto out_error;
xen_store_interface = gfn_to_virt(xen_store_gfn); break; case XS_PV:
xen_store_evtchn = xen_start_info->store_evtchn;
xen_store_gfn = xen_start_info->store_mfn;
xen_store_interface = gfn_to_virt(xen_store_gfn); break; case XS_HVM:
err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v); if (err) goto out_error; /* * Uninitialized hvm_params are zero and return no error. * Although it is theoretically possible to have * HVM_PARAM_STORE_PFN set to zero on purpose, in reality it is * not zero when valid. If zero, it means that Xenstore hasn't * been properly initialized. Instead of attempting to map a * wrong guest physical address return error. * * Also recognize all bits set as an invalid/uninitialized value.
*/ if (!v) {
err = -ENOENT; goto out_error;
} if (v == ~0ULL) {
wait = true;
} else { /* Avoid truncation on 32-bit. */ #if BITS_PER_LONG == 32 if (v > ULONG_MAX) {
pr_err("%s: cannot handle HVM_PARAM_STORE_PFN=%llx > ULONG_MAX\n",
__func__, v);
err = -EINVAL; goto out_error;
} #endif
xen_store_gfn = (unsignedlong)v;
xen_store_interface =
memremap(xen_store_gfn << XEN_PAGE_SHIFT,
XEN_PAGE_SIZE, MEMREMAP_WB); if (!xen_store_interface) {
pr_err("%s: cannot map HVM_PARAM_STORE_PFN=%llx\n",
__func__, v);
err = -EINVAL; goto out_error;
} if (xen_store_interface->connection != XENSTORE_CONNECTED)
wait = true;
} if (wait) {
err = bind_evtchn_to_irqhandler(xen_store_evtchn,
xenbus_late_init,
0, "xenstore_late_init",
&xb_waitq); if (err < 0) {
pr_err("xenstore_late_init couldn't bind irq err=%d\n",
err); goto out_error;
}
/* * HVM domains may not have a functional callback yet. In that * case let xs_init() be called from xenbus_probe(), which will * get invoked at an appropriate time.
*/ if (xen_store_domain_type != XS_HVM) {
err = xs_init(); if (err) {
pr_warn("Error initializing xenstore comms: %i\n", err); goto out_error;
}
}
if ((xen_store_domain_type != XS_LOCAL) &&
(xen_store_domain_type != XS_UNKNOWN))
xen_resume_notifier_register(&xenbus_resume_nb);
#ifdef CONFIG_XEN_COMPAT_XENFS /* * Create xenfs mountpoint in /proc for compatibility with * utilities that expect to find "xenbus" under "/proc/xen".
*/
proc_create_mount_point("xen"); #endif return 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.