Пример #1
0
struct vmm_devtree_node *vmm_devtree_irq_find_parent(
					struct vmm_devtree_node *child)
{
	struct vmm_devtree_node *p;
	const u32 *parp;

	if (!child) {
		return NULL;
	}
	vmm_devtree_ref_node(child);

	do {
		parp = vmm_devtree_attrval(child, "interrupt-parent");
		if (parp == NULL) {
			p = child->parent;
			vmm_devtree_ref_node(child->parent);
		} else {
			p = vmm_devtree_find_node_by_phandle(
				vmm_be32_to_cpu(*parp));
		}
		vmm_devtree_dref_node(child);
		child = p;
	} while (p && vmm_devtree_attrval(p, "#interrupt-cells") == NULL);

	return p;
}
Пример #2
0
int __init arch_cpu_early_init(void)
{
	const char *options;
	struct vmm_devtree_node *node;

	/*
	 * Host virtual memory, device tree, heap is up.
	 * Do necessary early stuff like iomapping devices
	 * memory or boot time memory reservation here.
	 */

	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_CHOSEN_NODE_NAME);
	if (!node) {
		return VMM_ENODEV;
	}

	if (vmm_devtree_read_string(node,
		VMM_DEVTREE_BOOTARGS_ATTR_NAME, &options) == VMM_OK) {
		vmm_parse_early_options(options);
	}

	vmm_devtree_dref_node(node);

	return VMM_OK;
}
Пример #3
0
static int __init process_acpi_sdt_table(char *tab_sign, u32 *tab_data)
{
    struct vmm_devtree_node *node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
                                    VMM_DEVTREE_MOTHERBOARD_NODE_NAME);
    /* FIXME: First find if tab_size already exists. */
    struct vmm_devtree_node *cnode = vmm_devtree_addnode(node, tab_sign);

    vmm_devtree_dref_node(node);
    if (!strncmp(tab_sign, APIC_SIGNATURE, strlen(APIC_SIGNATURE))) {
        struct acpi_madt_hdr *madt_hdr;
        madt_hdr = (struct acpi_madt_hdr *)tab_data;
        if (acpi_populate_ioapic_devtree(madt_hdr, cnode) != VMM_OK)
            return VMM_EFAIL;

        if (acpi_populate_lapic_devtree(madt_hdr, cnode) != VMM_OK)
            return VMM_EFAIL;
    } else if (!strncmp(tab_sign, HPET_SIGNATURE, strlen(HPET_SIGNATURE))) {
        struct acpi_hpet hpet_chip, *hpet;
        int nr_hpet_blks, i;
        char hpet_nm[256];

        if (acpi_read_sdt_at(tab_data,
                             (struct acpi_sdt_hdr *)&hpet_chip,
                             sizeof(struct acpi_hpet),
                             HPET_SIGNATURE) < 0) {
            return VMM_EFAIL;
        }

        hpet = (struct acpi_hpet *)tab_data;
        nr_hpet_blks = (hpet->hdr.len - sizeof(struct acpi_sdt_hdr))
                       /sizeof(struct acpi_timer_blocks);

        vmm_devtree_setattr(cnode, VMM_DEVTREE_NR_HPET_ATTR_NAME,
                            &nr_hpet_blks, VMM_DEVTREE_ATTRTYPE_UINT32,
                            sizeof(nr_hpet_blks), FALSE);

        for (i = 0; i < nr_hpet_blks; i++) {
            memset(hpet_nm, 0, sizeof(hpet_nm));
            vmm_sprintf(hpet_nm, VMM_DEVTREE_HPET_NODE_FMT, i);
            struct vmm_devtree_node *nnode = vmm_devtree_addnode(cnode, hpet_nm);

            BUG_ON(nnode == NULL);

            if (vmm_devtree_setattr(nnode, VMM_DEVTREE_HPET_ID_ATTR_NAME,
                                    &hpet->tmr_blks[i].asid,
                                    VMM_DEVTREE_ATTRTYPE_UINT32,
                                    sizeof(hpet->tmr_blks[i].asid), FALSE) != VMM_OK) {
                return VMM_EFAIL;
            }

            if (vmm_devtree_setattr(nnode, VMM_DEVTREE_HPET_PADDR_ATTR_NAME,
                                    &hpet->tmr_blks[i].base, VMM_DEVTREE_ATTRTYPE_PHYSADDR,
                                    sizeof(physical_addr_t), FALSE) != VMM_OK) {
                return VMM_EFAIL;
            }
        }
    }

    return VMM_OK;
}
Пример #4
0
static int __init scu_cpu_init(struct vmm_devtree_node *node,
				unsigned int cpu)
{
	int rc;
	u32 ncores;
	physical_addr_t pa;
	struct vmm_devtree_node *scu_node;

	/* Map SCU base */
	if (!scu_base) {
		scu_node = vmm_devtree_find_matching(NULL, scu_matches);
		if (!scu_node) {
			return VMM_ENODEV;
		}
		rc = vmm_devtree_regmap(scu_node, &scu_base, 0);
		vmm_devtree_dref_node(scu_node);
		if (rc) {
			return rc;
		}
	}

	/* Map clear address */
	rc = vmm_devtree_read_physaddr(node,
			VMM_DEVTREE_CPU_CLEAR_ADDR_ATTR_NAME, &pa);
	if (rc) {
		clear_addr[cpu] = 0x0;
	} else {
		clear_addr[cpu] = pa;
	}

	/* Map release address */
	rc = vmm_devtree_read_physaddr(node,
			VMM_DEVTREE_CPU_RELEASE_ADDR_ATTR_NAME, &pa);
	if (rc) {
		release_addr[cpu] = 0x0;
	} else {
		release_addr[cpu] = pa;
	}

	/* Check core count from SCU */
	ncores = scu_get_core_count((void *)scu_base);
	if (ncores <= cpu) {
		return VMM_ENOSYS;
	}

	/* Check SCU status */
	if (!scu_cpu_core_is_smp((void *)scu_base, cpu)) {
		return VMM_ENOSYS;
	}

	return VMM_OK;
}
Пример #5
0
static int __init bcm2836_early_init(struct vmm_devtree_node *node)
{
	int rc = VMM_OK;
	void *base;
	u32 prescaler, cntfreq;
	virtual_addr_t base_va;
	struct vmm_devtree_node *np;

	np = vmm_devtree_find_compatible(NULL, NULL, "brcm,bcm2836-l1-intc");
	if (!np) {
		return VMM_ENODEV;
	}

	rc = vmm_devtree_regmap(np, &base_va, 0);
	if (rc) {
		goto done;
	}
	base = (void *)base_va;

	cntfreq = generic_timer_reg_read(GENERIC_TIMER_REG_FREQ);
	switch (cntfreq) {
	case 19200000:
		prescaler = 0x80000000;
	case 1000000:
		prescaler = 0x06AAAAAB;
	default:
		prescaler = (u32)udiv64((u64)0x80000000 * (u64)cntfreq,
					(u64)19200000);
		break;
	};

	if (!prescaler) {
		rc = VMM_EINVALID;
		goto done_unmap;
	}

	vmm_writel(prescaler, base + LOCAL_TIMER_PRESCALER);

done_unmap:
	vmm_devtree_regunmap(node, base_va, 0);

done:
	vmm_devtree_dref_node(np);

	return rc;
}
Пример #6
0
static int __init realview_early_init(struct vmm_devtree_node *node)
{
	/* Initialize sysreg */
	realview_sysreg_of_early_init();

	/* Intialize realview clocking */
	realview_clk_init((void *)realview_system_base(), FALSE);

	/* Setup CLCD (before probing) */
	node = vmm_devtree_find_compatible(NULL, NULL, "arm,pl111");
	if (node) {
		node->system_data = &clcd_system_data;
	}
	vmm_devtree_dref_node(node);

	return VMM_OK;
}
Пример #7
0
int __init arch_board_final_init(void)
{
	int rc;
	struct vmm_devtree_node *node;
#if defined(CONFIG_VTEMU)
	struct fb_info *info;
#endif

	/* All VMM API's are available here */
	/* We can register a Board specific resource here */

	/* Find simple-bus node */
	node = vmm_devtree_find_compatible(NULL, NULL, "simple-bus");
	if (!node) {
		return VMM_ENODEV;
	}

	/* Do platform device probing using device driver framework */
	rc = vmm_platform_probe(node);
	vmm_devtree_dref_node(node);
	if (rc) {
		return rc;
	}

	/* Create VTEMU instace if available */
#if defined(CONFIG_VTEMU)
	info = fb_find("fb0");
	if (info) {
		generic_vt = vtemu_create(info->name, info, NULL);
	}
#endif

	/* Final init of generic boards with 
	 * matching nodeid table enteries.
	 */
	if (generic_board_matches) {
		vmm_devtree_iterate_matching(NULL,
					     generic_board_matches,
					     generic_board_final,
					     NULL);
	}

	return VMM_OK;
}
Пример #8
0
unsigned int vmm_devtree_irq_parse_map(struct vmm_devtree_node *dev,
					int index)
{
	int hirq = 0;
	struct vmm_devtree_phandle_args oirq = { .np = NULL, .args_count = 0 };

	if (vmm_devtree_irq_parse_one(dev, index, &oirq)) {
		return 0;
	}

	if (oirq.args_count) {
		hirq = vmm_devtree_irq_create_mapping(&oirq);
	}

	if (oirq.np) {
		vmm_devtree_dref_node(oirq.np);
	}

	return (hirq < 0) ? 0 : hirq;
}
Пример #9
0
int initrd_devtree_update(u64 start, u64 end)
{
	int rc = VMM_OK;
	struct vmm_devtree_node *node;

	/* Sanity checks */
	if (start >= end) {
		return VMM_EINVALID;
	}
	if (initrd_rbd) {
		return VMM_EBUSY;
	}

	/* There should be a /chosen node */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_CHOSEN_NODE_NAME);
	if (!node) {
		return VMM_ENODEV;
	}

	/* Update start attribute in /chosen node */
	rc = vmm_devtree_setattr(node, INITRD_START_ATTR2_NAME,
				 &start, VMM_DEVTREE_ATTRTYPE_UINT64,
				 sizeof(start), FALSE);
	if (rc) {
		goto done;
	}

	/* Update end attribute in /chosen node */
	rc = vmm_devtree_setattr(node, INITRD_END_ATTR2_NAME,
				 &end, VMM_DEVTREE_ATTRTYPE_UINT64,
				 sizeof(end), FALSE);
	if (rc) {
		goto done;
	}

done:
	vmm_devtree_dref_node(node);

	return rc;
}
Пример #10
0
void __init realview_sysreg_of_early_init(void)
{
	int err;
	virtual_addr_t base_va;
	struct vmm_devtree_node *node;

	if (realview_sysreg_base)
		return;

	node = vmm_devtree_find_compatible(NULL, NULL, "arm,realview-sysreg");
	if (node) {
		err = vmm_devtree_request_regmap(node, &base_va, 0,
						 "Realview Sysreg");
		if (err) {
			vmm_printf("%s: Faild to map registers (err %d)\n",
				   __func__, err);
			return;
		}		
		realview_sysreg_base = (void *)base_va;
		vmm_devtree_dref_node(node);
	}
}
Пример #11
0
static int cmd_host_info(struct vmm_chardev *cdev)
{
	int rc;
	const char *attr;
	unsigned long hwid;
	struct vmm_devtree_node *node;
	u32 total = vmm_host_ram_total_frame_count();

	attr = NULL;
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING);
	if (node) {
		vmm_devtree_read_string(node,
					VMM_DEVTREE_MODEL_ATTR_NAME, &attr);
		vmm_devtree_dref_node(node);
	}
	if (attr) {
		vmm_cprintf(cdev, "%-25s: %s\n", "Host Name", attr);
	} else {
		vmm_cprintf(cdev, "%-25s: %s\n", "Host Name", CONFIG_BOARD);
	}

	rc = vmm_smp_map_hwid(vmm_smp_bootcpu_id(), &hwid);
	if (rc)
		return rc;

	vmm_cprintf(cdev, "%-25s: 0x%lx\n", "Boot CPU Hardware ID", hwid);
	vmm_cprintf(cdev, "%-25s: %u\n", "Total Online CPUs",
		    vmm_num_online_cpus());
	vmm_cprintf(cdev, "%-25s: %u MB\n", "Total VAPOOL",
		    CONFIG_VAPOOL_SIZE_MB);
	vmm_cprintf(cdev, "%-25s: %lu MB\n", "Total RAM",
		    ((total *VMM_PAGE_SIZE) >> 20));

	arch_board_print_info(cdev);

	return VMM_OK;
}
Пример #12
0
int __init arch_smp_init_cpus(void)
{
	int rc;
	unsigned int i, cpu = 1;
	bool bootcpu_valid = false;
	struct vmm_devtree_node *dn, *cpus;

	cpus = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING "cpus");
	if (!cpus) {
		vmm_printf("%s: Failed to find cpus node\n",
			   __func__);
		return VMM_ENOTAVAIL;
	}

	dn = NULL;
	vmm_devtree_for_each_child(dn, cpus) {
		break;
	}
	if (!dn) {
		vmm_printf("%s: Failed to find node for boot cpu\n",
			   __func__);
		vmm_devtree_dref_node(cpus);
		return VMM_ENODEV;
	}

	rc = vmm_devtree_read_physaddr(dn,
			VMM_DEVTREE_REG_ATTR_NAME, &smp_logical_map(0));
	if (rc) {
		vmm_printf("%s: Failed to find reg property for boot cpu\n",
			   __func__);
		vmm_devtree_dref_node(dn);
		vmm_devtree_dref_node(cpus);
		return rc;
	}
	smp_read_ops(dn, 0);
	vmm_devtree_dref_node(dn);

	dn = NULL;
	vmm_devtree_for_each_child(dn, cpus) {
		physical_addr_t hwid;

		/*
		 * A cpu node with missing "reg" property is
		 * considered invalid to build a smp_logical_map
		 * entry.
		 */
		rc = vmm_devtree_read_physaddr(dn,
					VMM_DEVTREE_REG_ATTR_NAME, &hwid);
		if (rc) {
			vmm_printf("%s: missing reg property\n", dn->name);
			goto next;
		}

		/*
		 * Non affinity bits must be set to 0 in the DT
		 */
		if (hwid & ~MPIDR_HWID_BITMASK) {
			vmm_printf("%s: invalid reg property\n", dn->name);
			goto next;
		}

		/*
		 * Duplicate MPIDRs are a recipe for disaster. Scan
		 * all initialized entries and check for
		 * duplicates. If any is found just ignore the cpu.
		 * smp_logical_map was initialized to MPIDR_INVALID to
		 * avoid matching valid MPIDR values.
		 */
		for (i = 1; (i < cpu) && (i < CONFIG_CPU_COUNT); i++) {
			if (smp_logical_map(i) == hwid) {
				vmm_printf("%s: duplicate cpu reg properties"
					   " in the DT\n", dn->name);
				goto next;
			}
		}

		/*
		 * The numbering scheme requires that the boot CPU
		 * must be assigned logical id 0. Record it so that
		 * the logical map built from DT is validated and can
		 * be used.
		 */
		if (hwid == smp_logical_map(0)) {
			if (bootcpu_valid) {
				vmm_printf("%s: duplicate boot cpu reg property"
					   " in DT\n", dn->name);
				goto next;
			}

			bootcpu_valid = TRUE;

			/*
			 * smp_logical_map has already been
			 * initialized and the boot cpu doesn't need
			 * the enable-method so continue without
			 * incrementing cpu.
			 */
			continue;
		}

		if (cpu >= CONFIG_CPU_COUNT)
			goto next;

		if (smp_read_ops(dn, cpu) != 0)
			goto next;

		if (smp_cpu_ops[cpu]->cpu_init(dn, cpu))
			goto next;

		DPRINTF("%s: smp logical map CPU%0 -> HWID 0x%llx\n",
			__func__, cpu, hwid);
		smp_logical_map(cpu) = hwid;
next:
		cpu++;
	}
Пример #13
0
static int cmd_vfs_fdt_load(struct vmm_chardev *cdev,
			    const char *devtree_path,
			    const char *devtree_root_name,
			    const char *path,
			    int aliasc, char **aliasv)
{
	int a, fd, rc = VMM_OK;
	char *astr;
	const char *aname, *apath, *aattr, *atype;
	size_t fdt_rd;
	void *fdt_data, *val = NULL;
	u32 val_type, val_len = 0;
	struct stat st;
	struct vmm_devtree_node *root, *anode, *node;
	struct vmm_devtree_node *parent;
	struct fdt_fileinfo fdt;

	parent = vmm_devtree_getnode(devtree_path);
	if (!parent) {
		vmm_cprintf(cdev, "Devtree path %s does not exist.\n",
			    devtree_path);
		return VMM_EINVALID;
	}

	root = vmm_devtree_getchild(parent, devtree_root_name);
	if (root) {
		vmm_devtree_dref_node(root);
		vmm_cprintf(cdev, "Devtree path %s/%s already exist.\n",
			    devtree_path, devtree_root_name);
		rc = VMM_EINVALID;
		goto fail;
	}

	fd = vfs_open(path, O_RDONLY, 0);
	if (fd < 0) {
		vmm_cprintf(cdev, "Failed to open %s\n", path);
		rc = fd;
		goto fail;
	}

	rc = vfs_fstat(fd, &st);
	if (rc) {
		vmm_cprintf(cdev, "Path %s does not exist.\n", path);
		goto fail_closefd;
	}

	if (!(st.st_mode & S_IFREG)) {
		vmm_cprintf(cdev, "Path %s should be regular file.\n", path);
		rc = VMM_EINVALID;
		goto fail_closefd;
	}

	if (!st.st_size) {
		vmm_cprintf(cdev, "File %s has zero %d bytes.\n", path);
		rc = VMM_EINVALID;
		goto fail_closefd;
	}

	if (st.st_size > VFS_MAX_FDT_SZ) {
		vmm_cprintf(cdev, "File %s has size %d bytes (> %d bytes).\n",
			    path, (long)st.st_size, VFS_MAX_FDT_SZ);
		rc = VMM_EINVALID;
		goto fail_closefd;
	}

	fdt_data = vmm_zalloc(VFS_MAX_FDT_SZ);
	if (!fdt_data) {
		rc = VMM_ENOMEM;
		goto fail_closefd;
	}

	fdt_rd = vfs_read(fd, fdt_data, VFS_MAX_FDT_SZ);
	if (fdt_rd < st.st_size) {
		rc = VMM_EIO;
		goto fail_freedata;
	}

	rc = libfdt_parse_fileinfo((virtual_addr_t)fdt_data, &fdt);
	if (rc) {
		goto fail_freedata;
	}

	root = NULL;
	rc = libfdt_parse_devtree(&fdt, &root, devtree_root_name, parent);
	if (rc) {
		goto fail_freedata;
	}

	anode = vmm_devtree_getchild(root, VMM_DEVTREE_ALIASES_NODE_NAME);

	for (a = 0; a < aliasc; a++) {
		if (!anode) {
			vmm_cprintf(cdev, "Error: %s node not available\n",
				    VMM_DEVTREE_ALIASES_NODE_NAME);
			continue;
		}

		astr = aliasv[a];

		aname = astr;
		while (*astr != '\0' && *astr != ',') {
			astr++;
		}
		if (*astr == ',') {
			*astr = '\0';
			astr++;
		}

		if (*astr == '\0') {
			continue;
		}
		aattr = astr;
		while (*astr != '\0' && *astr != ',') {
			astr++;
		}
		if (*astr == ',') {
			*astr = '\0';
			astr++;
		}

		if (*astr == '\0') {
			continue;
		}
		atype = astr;
		while (*astr != '\0' && *astr != ',') {
			astr++;
		}
		if (*astr == ',') {
			*astr = '\0';
			astr++;
		}

		if (*astr == '\0') {
			continue;
		}

		if (vmm_devtree_read_string(anode, aname, &apath)) {
			vmm_cprintf(cdev, "Error: Failed to read %s attribute "
				    "of %s node\n", aname,
				    VMM_DEVTREE_ALIASES_NODE_NAME);
			continue;
		}

		node = vmm_devtree_getchild(root, apath);
		if (!node) {
			vmm_cprintf(cdev, "Error: %s node not found under "
				    "%s/%s\n", apath, devtree_path,
				    devtree_root_name);
			continue;
		}

		if (!strcmp(atype, "unknown")) {
			val = NULL;
			val_len = 0;
			val_type = VMM_DEVTREE_MAX_ATTRTYPE;
		} else if (!strcmp(atype, "string")) {
			val_len = strlen(astr) + 1;
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			strcpy(val, astr);
			val_type = VMM_DEVTREE_ATTRTYPE_STRING;
		} else if (!strcmp(atype, "bytes")) {
			val_len = 1;
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			*((u8 *)val) = strtoul(astr, NULL, 0);
			val_type = VMM_DEVTREE_ATTRTYPE_BYTEARRAY;
		} else if (!strcmp(atype, "uint32")) {
			val_len = 4;
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			*((u32 *)val) = strtoul(astr, NULL, 0);
			val_type = VMM_DEVTREE_ATTRTYPE_UINT32;
		} else if (!strcmp(atype, "uint64")) {
			val_len = 8;
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			*((u64 *)val) = strtoull(astr, NULL, 0);
			val_type = VMM_DEVTREE_ATTRTYPE_UINT64;
		} else if (!strcmp(atype, "physaddr")) {
			val_len = sizeof(physical_addr_t);
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			*((physical_addr_t *)val) = strtoull(astr, NULL, 0);
			val_type = VMM_DEVTREE_ATTRTYPE_PHYSADDR;
		} else if (!strcmp(atype, "physsize")) {
			val_len = sizeof(physical_size_t);
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			*((physical_size_t *)val) = strtoull(astr, NULL, 0);
			val_type = VMM_DEVTREE_ATTRTYPE_PHYSSIZE;
		} else if (!strcmp(atype, "virtaddr")) {
			val_len = sizeof(virtual_addr_t);
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			*((virtual_addr_t *)val) = strtoull(astr, NULL, 0);
			val_type = VMM_DEVTREE_ATTRTYPE_VIRTADDR;
		} else if (!strcmp(atype, "virtsize")) {
			val_len = sizeof(virtual_size_t);
			val = vmm_zalloc(val_len);
			if (!val) {
				vmm_cprintf(cdev, "Error: vmm_zalloc(%d) "
					    "failed\n", val_len);
				goto next_iter;
			}
			*((virtual_size_t *)val) = strtoull(astr, NULL, 0);
			val_type = VMM_DEVTREE_ATTRTYPE_VIRTSIZE;
		} else {
			vmm_cprintf(cdev, "Error: Invalid attribute type %s\n",
				    atype);
			goto next_iter;
		}

		if (val && (val_len > 0)) {
			vmm_devtree_setattr(node, aattr, val,
					    val_type, val_len, FALSE);
			vmm_free(val);
		}

next_iter:
		vmm_devtree_dref_node(node);
	}

	vmm_devtree_dref_node(anode);

fail_freedata:
	vmm_free(fdt_data);
fail_closefd:
	vfs_close(fd);
fail:
	vmm_devtree_dref_node(parent);
	return rc;
}
Пример #14
0
static int __init lwip_netstack_init(void)
{
	int rc;
	struct vmm_netswitch *nsw;
	struct vmm_devtree_node *node;
	const char *str;
	u8 ip[] = {169, 254, 1, 1};
	u8 mask[] = {255, 255, 255, 0};
	ip_addr_t __ip, __nm, __gw;

	/* Clear lwIP state */
	memset(&lns, 0, sizeof(lns));

	/* Get netstack device tree node if available */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_VMMINFO_NODE_NAME
				   VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_VMMNET_NODE_NAME
				   VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_NETSTACK_NODE_NAME);

	/* Retrive preferred IP address */
	if (vmm_devtree_read_string(node, "ipaddr", &str) == VMM_OK) {
		/* Read ip address from netstack node */
		str2ipaddr(ip, str);
	}

	/* Retrive preferred IP address */
	if (vmm_devtree_read_string(node, "netmask", &str) == VMM_OK) {
		/* Read network mask from netstack node */
		str2ipaddr(mask, str);
	}

	/* Retrive preferred netswitch */
	if (vmm_devtree_read_string(node, "netswitch", &str) == VMM_OK) {
		/* Find netswitch with given name */
		nsw = vmm_netswitch_find(str);
	} else {
		/* Get default netswitch */
		nsw = vmm_netswitch_default();
	}
	if (!nsw) {
		vmm_panic("%s: No netswitch found\n", __func__);
	}

	/* Release netstack device tree node */
	vmm_devtree_dref_node(node);

	/* Allocate a netport */
	lns.port = vmm_netport_alloc("lwip-netport", VMM_NETPORT_DEF_QUEUE_SIZE);
	if (!lns.port) {
		vmm_printf("%s: vmm_netport_alloc() failed\n", __func__);
		rc = VMM_ENOMEM;
		goto fail;
	}

	/* Setup a netport */
	lns.port->mtu = 1500;
	lns.port->link_changed = lwip_set_link;
	lns.port->can_receive = lwip_can_receive;
	lns.port->switch2port_xfer = lwip_switch2port_xfer;
	lns.port->priv = &lns;

	/* Register a netport */
	rc = vmm_netport_register(lns.port);
	if (rc) {
		goto fail1;
	}

	/* Initialize lwIP + TCP/IP APIs */
	tcpip_init(NULL, NULL);

	/* Add netif */
	IP4_ADDR(&__ip, ip[0],ip[1],ip[2],ip[3]);
	IP4_ADDR(&__nm, mask[0],mask[1],mask[2],mask[3]);
	IP4_ADDR(&__gw, ip[0],ip[1],ip[2],ip[3]);
	netif_add(&lns.nif, &__ip, &__nm, &__gw, &lns,
		  lwip_netstack_netif_init, ethernet_input);

	/* Set default netif */
	netif_set_default(&lns.nif);

	/* Attach netport with netswitch 
	 * Note: This will cause netport link_change()
	 */
	rc = vmm_netswitch_port_add(nsw, lns.port);
	if (rc) {
		goto fail2;
	}

#if !defined(PING_USE_SOCKETS)
	/* Initalize RAW PCB for ping */
	ping_raw_init();
#endif

	return VMM_OK;

fail2:
	vmm_netport_unregister(lns.port);
fail1:
	vmm_netport_free(lns.port);
fail:
	return rc;
}
Пример #15
0
static int __init initrd_driver_init(void)
{
	struct vmm_devtree_node *node;
	u64 initrd_start, initrd_end;

	/* There should be a /chosen node */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_CHOSEN_NODE_NAME);
	if (!node) {
		vmm_printf("initrd: No chosen node\n", __func__);
		return VMM_ENODEV;
	}

	/* Is there a start attribute */
	if (vmm_devtree_read_u64(node,
		INITRD_START_ATTR_NAME, &initrd_start) != VMM_OK) {
		if (vmm_devtree_read_u64(node,
			INITRD_START_ATTR2_NAME, &initrd_start) != VMM_OK) {
			vmm_printf("initrd: %s/%s attribute not found\n",
				   INITRD_START_ATTR_NAME,
				   INITRD_START_ATTR2_NAME);
			goto error;
		}
	}

	/* If so is there also a end attribte */
	if (vmm_devtree_read_u64(node,
		INITRD_END_ATTR_NAME, &initrd_end) != VMM_OK) {
		if (vmm_devtree_read_u64(node,
			INITRD_END_ATTR2_NAME, &initrd_end) != VMM_OK) {
			vmm_printf("initrd: %s/%s attribute not found\n",
				   INITRD_END_ATTR_NAME,
				   INITRD_END_ATTR2_NAME);
			goto error;
		}
	}

	/* Let's do a little bit os sanity check */
	if (initrd_end <= initrd_start) {
		vmm_printf("initrd: error: initrd_start > initrd_end\n");
		goto error;
	}

	/* OK, we know where the initrd device is located */
	if ((initrd_rbd = rbd_create("initrd",
				(physical_addr_t)initrd_start,
				(physical_size_t)(initrd_end -
					  initrd_start), true))
				== NULL) {
		vmm_printf("initrd: rbd_create() failed\n");
		goto error;
	}

	vmm_printf("initrd: RBD created at 0x%llx - 0x%llx\n",
		   initrd_start, initrd_end);

 error:
	vmm_devtree_dref_node(node);

	return VMM_OK;
}
Пример #16
0
static int __init vmm_net_init(void)
{
	int rc = VMM_OK;
	struct vmm_devtree_node *node;

	rc = vmm_mbufpool_init();
	if (rc) {
		vmm_printf("%s: Failed to init mbuf pool\n", __func__);
		goto mbufpool_init_failed;
	}

	rc = vmm_netswitch_init();
	if (rc) {
		vmm_printf("%s: Failed to init netswitch\n", __func__);
		goto netswitch_init_failed;
	}

	rc = vmm_netport_init();
	if (rc) {
		vmm_printf("%s: Failed to init netport\n", __func__);
		goto netport_init_failed;
	}

	rc = vmm_hub_init();
	if (rc) {
		vmm_printf("%s: Failed to init hub\n", __func__);
		goto bridge_init_failed;
	}

	rc = vmm_bridge_init();
	if (rc) {
		vmm_printf("%s: Failed to init bridge\n", __func__);
		goto bridge_init_failed;
	}

	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_VMMINFO_NODE_NAME
				   VMM_DEVTREE_PATH_SEPARATOR_STRING "net");
	if (!node) {
		vmm_printf("%s: devtree node not found\n", __func__);
		goto net_devtree_probe_failed;
	}

	rc = vmm_devdrv_probe(node);
	vmm_devtree_dref_node(node);
	if (rc) {
		vmm_printf("%s: devtree node probe failed\n", __func__);
		goto net_devtree_probe_failed;
	}

	goto net_init_done;

net_devtree_probe_failed:
	vmm_bridge_exit();
bridge_init_failed:
	vmm_netport_exit();
netport_init_failed:
	vmm_netswitch_exit();
netswitch_init_failed:
	vmm_mbufpool_exit();
mbufpool_init_failed:

net_init_done:
	return rc;
}
Пример #17
0
int vmm_devtree_irq_parse_one(struct vmm_devtree_node *device, int index,
			      struct vmm_devtree_phandle_args *out_irq)
{
	struct vmm_devtree_node *p = NULL;
	struct vmm_devtree_attr *attr = NULL;
	u32 *intspec = NULL;
	u32 intsize = 0;
	u32 intlen = 0;
	int res = VMM_EINVALID;
	int i;

	if (!device || (index < 0) || !out_irq) {
		return VMM_EINVALID;
	}

	pr_debug("%s: dev=%s, index=%d\n", __func__, device->name, index);

	attr = vmm_devtree_getattr(device, "interrupts");
	if (NULL == attr) {
		return VMM_EINVALID;
	}

	intlen = attr->len / sizeof(u32);
	intspec = attr->value;
	pr_debug(" intspec=%d intlen=%d\n", vmm_be32_to_cpu(*intspec), intlen);

	/* Look for the interrupt parent. */
	p = vmm_devtree_irq_find_parent(device);
	if (NULL == p) {
		/* If no interrupt-parent fount then try
		 * the original vmm_devtree_irq_get() API
		 */
		res = vmm_devtree_irq_get(device, &intsize, index);
		if (res != VMM_OK) {
			return res;
		}
		out_irq->np = NULL;
		out_irq->args_count = 1;
		out_irq->args[0] = intsize;
		return VMM_OK;
	}

	/* Get size of interrupt specifier */
	res = vmm_devtree_read_u32(p, "#interrupt-cells", &intsize);
	if (VMM_OK != res) {
		vmm_devtree_dref_node(p);
		return res;
	}

	pr_debug(" intsize=%d intlen=%d\n", intsize, intlen);

	/* Check index */
	if ((index + 1) * intsize > intlen) {
		vmm_devtree_dref_node(p);
		return VMM_EINVALID;
	}

	/* Copy intspec into irq structure */
	intspec += index * intsize;
	out_irq->np = p;
	out_irq->args_count = intsize;
	for (i = 0; i < intsize && i < VMM_MAX_PHANDLE_ARGS; i++) {
		out_irq->args[i] = vmm_be32_to_cpu(*intspec++);
	}

	return VMM_OK;
}