Example #1
0
int __init arch_defterm_init(void)
{
	int rc;
	const char *attr;
	struct vmm_devtree_node *node;
	const struct vmm_devtree_nodeid *nodeid;

	/* Find choosen console node */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_CHOSEN_NODE_NAME);
	if (!node) {
		return VMM_ENODEV;
	}

	rc = vmm_devtree_read_string(node,
				VMM_DEVTREE_CONSOLE_ATTR_NAME, &attr);
	if (rc) {
		return rc;
	}
   
	node = vmm_devtree_getnode(attr);
	if (!node) {
		return VMM_ENODEV;
	}

	/* Find appropriate defterm ops */
	nodeid = vmm_devtree_match_node(defterm_devid_table, node);
	if (nodeid) {
		ops = nodeid->data;
	}

	return ops->init(node);
}
Example #2
0
int __init arch_board_final_init(void)
{
	int rc;
	struct vmm_devtree_node *node;

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

	/* Do Probing using device driver framework */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
					VMM_DEVTREE_HOSTINFO_NODE_NAME
					VMM_DEVTREE_PATH_SEPARATOR_STRING
					"plb");

	if(!node) {
		return VMM_ENOTAVAIL;
	}

	rc = vmm_devdrv_probe(node, NULL);
	if(rc) {
		return rc;
	}

	return VMM_OK;
}
Example #3
0
int __init arch_clocksource_init(void)
{
	int rc;
	struct vmm_devtree_node *node;

	/* Map timer0 registers */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING "mct");
	if (!node) {
		rc = VMM_EFAIL;
		goto skip_mct_timer_init;
	}

	rc = vmm_devtree_clock_frequency(node, &mct_clk_rate);
	if (rc) {
		goto skip_mct_timer_init;
	}

	if (!mct_timer_base) {
		rc = vmm_devtree_regmap(node, &mct_timer_base, 0);
		if (rc) {
			return rc;
		}
	}

	/* Initialize mct as clocksource */
	rc = exynos4_clocksource_init(mct_timer_base, node->name, 300,
				      mct_clk_rate);
	if (rc) {
		return rc;
	}
 skip_mct_timer_init:

	return rc;
}
Example #4
0
static void cmd_host_info(struct vmm_chardev *cdev)
{
    const char *attr;
    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);
    }
    if (attr) {
        vmm_cprintf(cdev, "%-20s: %s\n", "Host Name", attr);
    } else {
        vmm_cprintf(cdev, "%-20s: %s\n", "Host Name", CONFIG_BOARD);
    }

    vmm_cprintf(cdev, "%-20s: %u\n", "Boot CPU",
                vmm_smp_bootcpu_id());
    vmm_cprintf(cdev, "%-20s: %u\n", "Total Online CPUs",
                vmm_num_online_cpus());
    vmm_cprintf(cdev, "%-20s: %u MB\n", "Total VAPOOL",
                CONFIG_VAPOOL_SIZE_MB);
    vmm_cprintf(cdev, "%-20s: %u MB\n", "Total RAM",
                ((total *VMM_PAGE_SIZE) >> 20));

    arch_board_print_info(cdev);
}
Example #5
0
int __init arch_defterm_init(void)
{
	int rc;
	u32 *val;
	struct vmm_devtree_node *node;

	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_HOSTINFO_NODE_NAME
				   VMM_DEVTREE_PATH_SEPARATOR_STRING "motherboard"
				   VMM_DEVTREE_PATH_SEPARATOR_STRING "iofpga"
				   VMM_DEVTREE_PATH_SEPARATOR_STRING "uart0");
	if (!node) {
		return VMM_ENODEV;
	}
	rc = vmm_devtree_regmap(node, &v2m_defterm_base, 0);
	if (rc) {
		return rc;
	}

	val = vmm_devtree_attrval(node, VMM_DEVTREE_CLOCK_RATE_ATTR_NAME);
	v2m_defterm_inclk = (val) ? *val : 24000000;

	val = vmm_devtree_attrval(node, "baudrate");
	v2m_defterm_baud = (val) ? *val : 115200;

	pl011_lowlevel_init(v2m_defterm_base,
			    v2m_defterm_baud, 
			    v2m_defterm_inclk);
	return VMM_OK;
}
Example #6
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;
}
Example #7
0
static struct clk * __init imx_obtain_fixed_clock_from_dt(const char *name)
{
	unsigned int len = 0;
	struct vmm_devtree_phandle_args phandle;
	struct clk *clk = ERR_PTR(-ENODEV);
	char *path;

	len = strlen(name) + strlen("/clocks/") + 1;
	if (NULL == (path = kmalloc(GFP_KERNEL, len)))
	{
		vmm_printf("Failed to allocate fixed clock \"%s\" path "
			   "string\n", name);
		return NULL;
	}

	sprintf(path, "/clocks/%s", name);

	phandle.np = vmm_devtree_getnode(path);
	kfree(path);

	if (phandle.np) {
		clk = of_clk_get_from_provider(&phandle);
		of_node_put(phandle.np);
	}
	return clk;
}
Example #8
0
int __init arch_smp_init_cpus(void)
{
	int rc;
	const char *str;
	physical_addr_t hwid;
	unsigned int i, cpus_count = 0, cpu = 1;
	bool bootcpu_valid = false;
	struct vmm_devtree_node *dn, *cpus;

	smp_init_ops();

	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) {
		str = NULL;
		rc = vmm_devtree_read_string(dn,
				VMM_DEVTREE_DEVICE_TYPE_ATTR_NAME, &str);
		if (rc || !str) {
			continue;
		}
		if (strcmp(str, VMM_DEVTREE_DEVICE_TYPE_VAL_CPU)) {
			continue;
		}
		cpus_count++;
	}
Example #9
0
int __init arch_board_final_init(void)
{
    int rc;
    struct vmm_devtree_node *node;
    struct vmm_chardev * cdev;

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

    /* Do Probing using device driver framework */
    node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
                               VMM_DEVTREE_HOSTINFO_NODE_NAME
                               VMM_DEVTREE_PATH_SEPARATOR_STRING "l3");

    if (!node) {
        return VMM_ENOTAVAIL;
    }

    rc = vmm_devdrv_probe(node, NULL);
    if (rc) {
        return rc;
    }

    /* Find uart0 character device and
     * set it as vmm_stdio character device */
    if ((cdev = vmm_chardev_find("uart0"))) {
        vmm_stdio_change_indevice(cdev);
        vmm_stdio_change_outdevice(cdev);
    }

    return VMM_OK;

}
Example #10
0
int __init arch_defterm_init(void)
{
	int rc;
	u32 *val;
	struct vmm_devtree_node *node;

	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_HOSTINFO_NODE_NAME
				   VMM_DEVTREE_PATH_SEPARATOR_STRING "soc"
				   VMM_DEVTREE_PATH_SEPARATOR_STRING "uart0");
	if (!node) {
		return VMM_ENODEV;
	}
	rc = vmm_devtree_regmap(node, &sun4i_uart_port.base, 0);
	if (rc) {
		return rc;
	}

	val = vmm_devtree_attrval(node, VMM_DEVTREE_CLOCK_RATE_ATTR_NAME);
	sun4i_uart_port.input_clock = (val) ? *val : 24000000;

	val = vmm_devtree_attrval(node, "baudrate");
	sun4i_uart_port.baudrate = (val) ? *val : 115200;

	val = vmm_devtree_attrval(node, "reg_align");
	sun4i_uart_port.reg_align = (val) ? *val : 4;

	uart_8250_lowlevel_init(&sun4i_uart_port);
	return VMM_OK;
}
Example #11
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;
}
Example #12
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_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);
	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;
}
Example #13
0
int __init arch_defterm_init(void)
{
	int rc;
	u32 *val;
	const char *attr;
	struct vmm_devtree_node *node;
	u32 imx_defterm_inclk;
	u32 imx_defterm_baud;

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

	attr = vmm_devtree_attrval(node, VMM_DEVTREE_CONSOLE_ATTR_NAME);
	if (!attr) {
		return VMM_ENODEV;
	}
   
	node = vmm_devtree_getnode(attr);
	if (!node) {
		return VMM_ENODEV;
	}

	rc = vmm_devtree_regmap(node, &imx_defterm_base, 0);
	if (rc) {
		return rc;
	}

	rc = vmm_devtree_clock_frequency(node, &imx_defterm_inclk);
	if (rc) {
		return rc;
	}

	val = vmm_devtree_attrval(node, "baudrate");
	imx_defterm_baud = (val) ? *val : 115200;

	imx_lowlevel_init(imx_defterm_base,
			  imx_defterm_baud, 
			  imx_defterm_inclk);

	return VMM_OK;
}
Example #14
0
int __init arch_smp_init_cpus(void)
{
	u32 ncores;
	int i, rc = VMM_OK;
	struct vmm_devtree_node *node;

	/* Get the PMU node in the dev tree */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING "pmu");
	if (!node) {
		return VMM_EFAIL;
	}

	/* Map the PMU physical address to virtual address */
	rc = vmm_devtree_regmap(node, &pmu_base, 0);
	if (rc) {
		return rc;
	}

	/* Get the SCU node in the dev tree */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING "scu");
	if (!node) {
		return VMM_EFAIL;
	}

	/* Map the SCU physical address to virtual address */
	rc = vmm_devtree_regmap(node, &scu_base, 0);
	if (rc) {
		return rc;
	}

	/* How many ARM core do we have */
	ncores = scu_get_core_count((void *)scu_base);

	/* Update the cpu_possible bitmap based on SCU */
	for (i = 0; i < CONFIG_CPU_COUNT; i++) {
		if ((i < ncores) &&
		    scu_cpu_core_is_smp((void *)scu_base, i)) {
			vmm_set_cpu_possible(i, TRUE);
		}
	}

	return VMM_OK;
}
Example #15
0
int __init arch_board_final_init(void)
{
	int rc;
	struct vmm_devtree_node *node;
	struct vmm_chardev * cdev;
#if defined(CONFIG_RTC)
	struct vmm_rtcdev * rdev;
#endif

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

#if 0 /* FIXME: */
	/* Map control registers */
	ca15x4_sys_base = vmm_host_iomap(VEXPRESS_SYS_BASE, 0x1000);

	/* Unlock Lockable registers */
	vmm_writel(VEXPRESS_SYS_LOCKVAL, 
		   (void *)(ca15x4_sys_base + VEXPRESS_SYS_LOCK_OFFSET));
#endif

	/* Do Probing using device driver framework */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_HOSTINFO_NODE_NAME
				   VMM_DEVTREE_PATH_SEPARATOR_STRING "nbridge");

	if (!node) {
		return VMM_ENOTAVAIL;
	}

	rc = vmm_devdrv_probe(node, NULL);
	if (rc) {
		return rc;
	}

	/* Find uart0 character device and 
	 * set it as vmm_stdio character device */
	if ((cdev = vmm_chardev_find("uart0"))) {
		vmm_stdio_change_indevice(cdev);
		vmm_stdio_change_outdevice(cdev);
	}

	/* Syncup wall-clock time from rtc0 */
#if defined(CONFIG_RTC)
	if ((rdev = vmm_rtcdev_find("rtc0"))) {
		if ((rc = vmm_rtcdev_sync_wallclock(rdev))) {
			return rc;
		}
	}
#endif

	return VMM_OK;
}
Example #16
0
int __cpuinit arch_clockchip_init(void)
{
	int rc;
	struct vmm_devtree_node *node;
	u32 val, cpu = vmm_smp_processor_id();

	if (!cpu) {
		/* Map timer0 registers */
		node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
					   "mct");
		if (!node) {
			goto skip_mct_timer_init;
		}

		if (!mct_timer_base) {
			rc = vmm_devtree_regmap(node, &mct_timer_base, 0);
			if (rc) {
				return rc;
			}
		}

		rc = vmm_devtree_clock_frequency(node, &mct_clk_rate);
		if (rc) {
			return rc;
		}

		/* Get MCT irq */
		rc = vmm_devtree_irq_get(node, &val, 0);
		if (rc) {
			return rc;
		}

		/* Initialize MCT as clockchip */
		rc = exynos4_clockchip_init(mct_timer_base, val, node->name,
					    300, mct_clk_rate, 0);
		if (rc) {
			return rc;
		}

	}
 skip_mct_timer_init:

#if CONFIG_SAMSUNG_MCT_LOCAL_TIMERS
	if (mct_timer_base) {
		exynos4_local_timer_init(mct_timer_base, 0, "mct_tick", 450,
					 mct_clk_rate);
	}
#endif

	return VMM_OK;
}
Example #17
0
static int __init daemon_mterm_init(void)
{
	u8 mterm_priority;
	u32 mterm_time_slice;
	struct vmm_devtree_node * node;
	const char * attrval;

	/* Reset the control structure */
	vmm_memset(&mtctrl, 0, sizeof(mtctrl));

	/* Retrive mterm time slice */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_VMMINFO_NODE_NAME);
	if (!node) {
		return VMM_EFAIL;
	}
	attrval = vmm_devtree_attrval(node,
				      "mterm_priority");
	if (attrval) {
		mterm_priority = *((u32 *) attrval);
	} else {
		mterm_priority = VMM_THREAD_DEF_PRIORITY;
	}
	attrval = vmm_devtree_attrval(node,
				      "mterm_time_slice");
	if (attrval) {
		mterm_time_slice = *((u32 *) attrval);
	} else {
		mterm_time_slice = VMM_THREAD_DEF_TIME_SLICE;
	}

	/* Create mterm thread */
	mtctrl.thread = vmm_threads_create("mterm", 
					   &mterm_main, 
					   NULL, 
					   mterm_priority,
					   mterm_time_slice);
	if (!mtctrl.thread) {
		vmm_panic("Creation of system critical thread failed.\n");
	}

	/* Start the mterm thread */
	vmm_threads_start(mtctrl.thread);

	return VMM_OK;
}
Example #18
0
int __init arch_smp_prepare_cpus(void)
{
	int rc = VMM_OK;
	struct vmm_devtree_node *node;
	virtual_addr_t ca9_scu_base;
	u32 ncores;
	int i;

	/* Get the SCU node in the dev tree */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_HOSTINFO_NODE_NAME
				   VMM_DEVTREE_PATH_SEPARATOR_STRING "scu");
	if (!node) {
		return VMM_EFAIL;
	}

	/* map the SCU physical address to virtual address */
	rc = vmm_devtree_regmap(node, &ca9_scu_base, 0);
	if (rc) {
		return rc;
	}

	/* How many ARM core do we have */
	ncores = scu_get_core_count((void *)ca9_scu_base);

	/* Find out the number of SMP-enabled cpu cores */
	for (i = 0; i < CONFIG_CPU_COUNT; i++) {
		/* build the possible CPU map */
		if ((i >= ncores)
		    || !scu_cpu_core_is_smp((void *)ca9_scu_base, i)) {
			/* Update the cpu_possible bitmap */
			vmm_set_cpu_possible(i, 0);
		} else {
			vmm_set_cpu_possible(i, 1);
		}
	}

	/* Enable snooping through SCU */
	scu_enable((void *)ca9_scu_base);

	/* unmap the SCU node */
	rc = vmm_devtree_regunmap(node, ca9_scu_base, 0);

	return rc;
}
Example #19
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;
}
Example #20
0
int __init arch_smp_start_cpu(u32 cpu)
{
	const struct vmm_cpumask *mask;
	int rc;
	struct vmm_devtree_node *node;
	virtual_addr_t ca9_pmu_base;

	if (cpu == 0) {
		/* Nothing to do for first CPU */
		return VMM_OK;
	}

	/* Get the PMU node in the dev tree */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_HOSTINFO_NODE_NAME
				   VMM_DEVTREE_PATH_SEPARATOR_STRING "pmu");
	if (!node) {
		return VMM_EFAIL;
	}

	/* map the PMU physical address to virtual address */
	rc = vmm_devtree_regmap(node, &ca9_pmu_base, 0);
	if (rc) {
		return rc;
	}

	mask = get_cpu_mask(cpu);

	/* Write the entry address for the secondary cpus */
	vmm_writel((u32)_load_start, (void *)ca9_pmu_base + 0x814);

	/* unmap the PMU node */
	rc = vmm_devtree_regunmap(node, ca9_pmu_base, 0);

	/* Wakeup target cpu from wfe/wfi by sending an IPI */
	gic_raise_softirq(mask, 0);

	return rc;
}
Example #21
0
int __init arch_board_final_init(void)
{
	int rc;
	struct vmm_devtree_node *node;
	struct vmm_chardev * cdev;

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

	/* Map control registers */
	pba8_sys_base = vmm_host_iomap(REALVIEW_SYS_BASE, 0x1000);

	/* Unlock Lockable registers */
	vmm_writel(REALVIEW_SYS_LOCKVAL, 
		   (void *)(pba8_sys_base + REALVIEW_SYS_LOCK_OFFSET));

	/* Do Probing using device driver framework */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_HOSTINFO_NODE_NAME
				   VMM_DEVTREE_PATH_SEPARATOR_STRING "nbridge");

	if (!node) {
		return VMM_ENOTAVAIL;
	}

	rc = vmm_devdrv_probe(node);
	if (rc) {
		return rc;
	}

	/* Find uart0 character device and 
	 * set it as vmm_stdio character device */
	if ((cdev = vmm_chardev_find("uart0"))) {
		vmm_stdio_change_device(cdev);
	}

	return VMM_OK;
}
Example #22
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;
}
Example #23
0
int __init arch_cpu_early_init(void)
{
	char *attr;
	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;
	}

	attr = vmm_devtree_attrval(node, VMM_DEVTREE_BOOTARGS_ATTR_NAME);
	if (attr) {
		vmm_parse_early_options(attr);
	}

	return VMM_OK;
}
Example #24
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++;
	}
Example #25
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;
}
Example #26
0
static void system_init_work(struct vmm_work *work)
{
#define BOOTCMD_WIDTH		256
	int ret;
	char bcmd[BOOTCMD_WIDTH];
	const char *str;
	u32 c, freed;
	struct vmm_chardev *cdev;
#if defined(CONFIG_RTC)
	struct vmm_rtcdev *rdev;
#endif
	struct vmm_devtree_node *node, *node1;

	/* Initialize command manager */
	vmm_printf("Initialize Command Manager\n");
	ret = vmm_cmdmgr_init();
	if (ret) {
		vmm_panic("Error %d\n", ret);
	}

	/* Initialize device driver framework */
	vmm_printf("Initialize Device Driver Framework\n");
	ret = vmm_devdrv_init();
	if (ret) {
		vmm_panic("Error %d\n", ret);
	}

	/* Initialize device emulation framework */
	vmm_printf("Initialize Device Emulation Framework\n");
	ret = vmm_devemu_init();
	if (ret) {
		vmm_panic("Error %d\n", ret);
	}

	/* Initialize character device framework */
	vmm_printf("Initialize Character Device Framework\n");
	ret = vmm_chardev_init();
	if (ret) {
		vmm_panic("Error %d\n", ret);
	}

	/* Initialize virtual serial port framework */
	vmm_printf("Initialize Virtual Serial Port Framework\n");
	ret = vmm_vserial_init();
	if (ret) {
		vmm_panic("Error %d\n", ret);
	}

#if defined(CONFIG_SMP)
	/* Poll for all present CPUs to become online */
	/* Note: There is a timeout of 1 second */
	/* Note: The modules might use SMP IPIs or might have per-cpu context 
	 * so, we do this before vmm_modules_init() in-order to make sure that 
	 * correct number of online CPUs are visible to all modules.
	 */
	ret = 1000;
	while(ret--) {
		int all_cpu_online = 1;

		for_each_present_cpu(c) {
			if (!vmm_cpu_online(c)) {
				all_cpu_online = 0;
			}
		}

		if (all_cpu_online) {
			break;
		}

		vmm_mdelay(1);
	}
#endif

	/* Initialize hypervisor modules */
	vmm_printf("Initialize Hypervisor Modules\n");
	ret = vmm_modules_init();
	if (ret) {
		vmm_panic("Error %d\n", ret);
	}

	/* Initialize cpu final */
	vmm_printf("Initialize CPU Final\n");
	ret = arch_cpu_final_init();
	if (ret) {
		vmm_panic("Error %d\n", ret);
	}

	/* Intialize board final */
	vmm_printf("Initialize Board Final\n");
	ret = arch_board_final_init();
	if (ret) {
		vmm_panic("Error %d\n", ret);
	}

	/* Print status of present host CPUs */
	for_each_present_cpu(c) {
		if (vmm_cpu_online(c)) {
			vmm_printf("CPU%d: Online\n", c);
		} else {
			vmm_printf("CPU%d: Possible\n", c);
		}
	}
	vmm_printf("Brought Up %d CPUs\n", vmm_num_online_cpus());

	/* Free init memory */
	vmm_printf("Freeing init memory: ");
	freed = vmm_host_free_initmem();
	vmm_printf("%dK\n", freed);

	/* Process attributes in chosen node */
	node = vmm_devtree_getnode(VMM_DEVTREE_PATH_SEPARATOR_STRING
				   VMM_DEVTREE_CHOSEN_NODE_NAME);
	if (node) {
		/* Find character device based on console attribute */
		str = vmm_devtree_attrval(node, VMM_DEVTREE_CONSOLE_ATTR_NAME);
		if (!(cdev = vmm_chardev_find(str))) {
			if ((node1 = vmm_devtree_getnode(str))) {
				cdev = vmm_chardev_find(node1->name);
			}
		}
		/* Set chosen console device as stdio device */
		if (cdev) {
			vmm_printf("Change stdio device to %s\n", cdev->name);
			vmm_stdio_change_device(cdev);
		}

#if defined(CONFIG_RTC)
		/* Find rtc device based on rtcdev attribute */
		str = vmm_devtree_attrval(node, VMM_DEVTREE_RTCDEV_ATTR_NAME);
		if (!(rdev = vmm_rtcdev_find(str))) {
			if ((node1 = vmm_devtree_getnode(str))) {
				rdev = vmm_rtcdev_find(node1->name);
			}
		}
		/* Syncup wallclock time with chosen rtc device */
		if (rdev) {
			ret = vmm_rtcdev_sync_wallclock(rdev);
			vmm_printf("Syncup wallclock using %s", rdev->name);
			if (ret) {
				vmm_printf("(error %d)", ret);
			}
			vmm_printf("\n");
		}
#endif

		/* Execute boot commands */
		str = vmm_devtree_attrval(node, VMM_DEVTREE_BOOTCMD_ATTR_NAME);
		if (str) {
			c = vmm_devtree_attrlen(node, VMM_DEVTREE_BOOTCMD_ATTR_NAME);
			while (c) {
#if defined(CONFIG_VERBOSE_MODE)
				/* Print boot command */
				vmm_printf("bootcmd: %s\n", str);
#endif
				/* Execute boot command */
				strlcpy(bcmd, str, sizeof(bcmd));
				cdev = vmm_stdio_device();
				vmm_cmdmgr_execute_cmdstr(cdev, bcmd, NULL);
				/* Next boot command */
				c -= strlen(str) + 1;
				str += strlen(str) + 1;
			}
		}
	}
}
Example #27
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;
}
Example #28
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;
}