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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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); } }
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; }
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++; }
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; }
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; }
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; }
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; }
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; }