static int __init xenbus_init()

in xenbus/xenbus_probe.c [910:1014]


static int __init xenbus_init(void)
{
	int err;
	uint64_t v = 0;
	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;
	if (xen_hvm_domain() && 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_EVTCHN, &v);
		if (err)
			goto out_error;
		xen_store_evtchn = (int)v;
		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 value.
		 */
		if (!v || !~v) {
			err = -ENOENT;
			goto out_error;
		}
		/* 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 = (unsigned long)v;
		xen_store_interface =
			xen_remap(xen_store_gfn << XEN_PAGE_SHIFT,
				  XEN_PAGE_SIZE);
		break;
	default:
		pr_warn("Xenstore state unknown\n");
		break;
	}

	/*
	 * 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;

out_error:
	xen_store_domain_type = XS_UNKNOWN;
	return err;
}