int __init arch_xen_unpopulated_init(struct resource **res)
{
	struct device_node *np;
	struct resource *regs, *tmp_res;
	uint64_t min_gpaddr = -1, max_gpaddr = 0;
	unsigned int i, nr_reg = 0;
	int rc;

	if (!xen_domain())
		return -ENODEV;

	if (!acpi_disabled)
		return -ENODEV;

	np = of_find_compatible_node(NULL, NULL, "xen,xen");
	if (WARN_ON(!np))
		return -ENODEV;

	/* Skip region 0 which is reserved for grant table space */
	while (of_get_address(np, nr_reg + EXT_REGION_INDEX, NULL, NULL))
		nr_reg++;

	if (!nr_reg) {
		pr_err("No extended regions are found\n");
		of_node_put(np);
		return -EINVAL;
	}

	regs = kcalloc(nr_reg, sizeof(*regs), GFP_KERNEL);
	if (!regs) {
		of_node_put(np);
		return -ENOMEM;
	}

	/*
	 * Create resource from extended regions provided by the hypervisor to be
	 * used as unused address space for Xen scratch pages.
	 */
	for (i = 0; i < nr_reg; i++) {
		rc = of_address_to_resource(np, i + EXT_REGION_INDEX, &regs[i]);
		if (rc)
			goto err;

		if (max_gpaddr < regs[i].end)
			max_gpaddr = regs[i].end;
		if (min_gpaddr > regs[i].start)
			min_gpaddr = regs[i].start;
	}

	xen_resource.start = min_gpaddr;
	xen_resource.end = max_gpaddr;

	/*
	 * Mark holes between extended regions as unavailable. The rest of that
	 * address space will be available for the allocation.
	 */
	for (i = 1; i < nr_reg; i++) {
		resource_size_t start, end;

		/* There is an overlap between regions */
		if (regs[i - 1].end + 1 > regs[i].start) {
			rc = -EINVAL;
			goto err;
		}

		/* There is no hole between regions */
		if (regs[i - 1].end + 1 == regs[i].start)
			continue;

		start = regs[i - 1].end + 1;
		end = regs[i].start - 1;

		tmp_res = kzalloc(sizeof(*tmp_res), GFP_KERNEL);
		if (!tmp_res) {
			rc = -ENOMEM;
			goto err;
		}

		tmp_res->name = "Unavailable space";
		tmp_res->start = start;
		tmp_res->end = end;

		rc = insert_resource(&xen_resource, tmp_res);
		if (rc) {
			pr_err("Cannot insert resource %pR (%d)\n", tmp_res, rc);
			kfree(tmp_res);
			goto err;
		}
	}

	*res = &xen_resource;

err:
	of_node_put(np);
	kfree(regs);
	return rc;
}
int __init arch_xen_unpopulated_init(struct resource **res)
{
	struct device_node *np;
	struct resource *regs, *tmp_res;
	uint64_t min_gpaddr = -1, max_gpaddr = 0;
	unsigned int i, nr_reg = 0;
	int rc;

	if (!xen_domain())
		return -ENODEV;

	if (!acpi_disabled)
		return -ENODEV;

	np = of_find_compatible_node(NULL, NULL, "xen,xen");
	if (WARN_ON(!np))
		return -ENODEV;

	 
	while (of_get_address(np, nr_reg + EXT_REGION_INDEX, NULL, NULL))
		nr_reg++;

	if (!nr_reg) {
		pr_err("No extended regions are found\n");
		of_node_put(np);
		return -EINVAL;
	}

	regs = kcalloc(nr_reg, sizeof(*regs), GFP_KERNEL);
	if (!regs) {
		of_node_put(np);
		return -ENOMEM;
	}

	 
	for (i = 0; i < nr_reg; i++) {
		rc = of_address_to_resource(np, i + EXT_REGION_INDEX, &regs[i]);
		if (rc)
			goto err;

		if (max_gpaddr < regs[i].end)
			max_gpaddr = regs[i].end;
		if (min_gpaddr > regs[i].start)
			min_gpaddr = regs[i].start;
	}

	xen_resource.start = min_gpaddr;
	xen_resource.end = max_gpaddr;

	 
	for (i = 1; i < nr_reg; i++) {
		resource_size_t start, end;

		 
		if (regs[i - 1].end + 1 > regs[i].start) {
			rc = -EINVAL;
			goto err;
		}

		 
		if (regs[i - 1].end + 1 == regs[i].start)
			continue;

		start = regs[i - 1].end + 1;
		end = regs[i].start - 1;

		tmp_res = kzalloc(sizeof(*tmp_res), GFP_KERNEL);
		if (!tmp_res) {
			rc = -ENOMEM;
			goto err;
		}

		tmp_res->name = "Unavailable space";
		tmp_res->start = start;
		tmp_res->end = end;

		rc = insert_resource(&xen_resource, tmp_res);
		if (rc) {
			pr_err("Cannot insert resource %pR (%d)\n", tmp_res, rc);
			kfree(tmp_res);
			goto err;
		}
	}

	*res = &xen_resource;

err:
	of_node_put(np);
	kfree(regs);
	return rc;
}