void target_init(void) { paddr_t buf_vaddr; void *hdr_addr; /* TODO: Move into zynq_common once the init order is sorted out with gem_init needing * pktbufs, and app init running after target_init */ if (vmm_alloc_contiguous(vmm_get_kernel_aspace(), "pktbuf_headers", ZYNQ_PKTBUF_CNT * sizeof(pktbuf_buf_t), (void **)&hdr_addr, 0, 0, ARCH_MMU_FLAG_CACHED) < 0) { printf("Failed to initialize pktbuf hdr slab\n"); return; } for (size_t i = 0; i < ZYNQ_PKTBUF_CNT; i++) { pktbuf_create((void *)hdr_addr, sizeof(pktbuf_t)); hdr_addr += sizeof(pktbuf_t); } if (vmm_alloc_contiguous(vmm_get_kernel_aspace(), "pktbuf_buffers", ZYNQ_PKTBUF_CNT * sizeof(pktbuf_buf_t), (void **)&buf_vaddr, 0, 0, ARCH_MMU_FLAG_UNCACHED) < 0) { printf("Failed to initialize pktbuf vm slab\n"); return; } pktbuf_create_bufs((void *)buf_vaddr, ZYNQ_PKTBUF_CNT * sizeof(pktbuf_buf_t)); gem_init(GEM0_BASE); register_gpio_int_handler(ZYBO_BTN5, toggle_ledy, NULL); zynq_unmask_gpio_interrupt(ZYBO_BTN5); }
static int mem_test(int argc, const cmd_args *argv) { if (argc < 2) { printf("not enough arguments\n"); usage: printf("usage: %s <length>\n", argv[0].str); return -1; } void *ptr; size_t len = argv[1].u; #if WITH_KERNEL_VMM /* rounding up len to the next page */ len = PAGE_ALIGN(len); if (len == 0) { printf("invalid length\n"); goto usage; } /* allocate a region to test in */ status_t err = vmm_alloc_contiguous(vmm_get_kernel_aspace(), "memtest", len, &ptr, 0, 0, ARCH_MMU_FLAG_UNCACHED); if (err < 0) { printf("error %d allocating test region\n", err); return -1; } paddr_t pa; arch_mmu_query((vaddr_t)ptr, &pa, 0); printf("physical address 0x%lx\n", pa); #else /* allocate from the heap */ ptr = malloc(len); if (!ptr ) { printf("error allocating test area from heap\n"); return -1; } #endif printf("got buffer at %p of length 0x%lx\n", ptr, len); /* run the tests */ do_mem_tests(ptr, len); #if WITH_KERNEL_VMM // XXX free memory region here printf("NOTE: leaked memory\n"); #else free(ptr); #endif return 0; }
status_t virtio_alloc_ring(struct virtio_device *dev, uint index, uint16_t len) { LTRACEF("dev %p, index %u, len %u\n", dev, index, len); DEBUG_ASSERT(dev); DEBUG_ASSERT(len > 0 && ispow2(len)); DEBUG_ASSERT(index < MAX_VIRTIO_RINGS); if (len == 0 || !ispow2(len)) return ERR_INVALID_ARGS; struct vring *ring = &dev->ring[index]; /* allocate a ring */ size_t size = vring_size(len, PAGE_SIZE); LTRACEF("need %zu bytes\n", size); #if WITH_KERNEL_VM void *vptr; status_t err = vmm_alloc_contiguous(vmm_get_kernel_aspace(), "virtio_ring", size, &vptr, 0, 0, ARCH_MMU_FLAG_UNCACHED_DEVICE); if (err < 0) return ERR_NO_MEMORY; LTRACEF("allocated virtio_ring at va %p\n", vptr); /* compute the physical address */ paddr_t pa; err = arch_mmu_query((vaddr_t)vptr, &pa, NULL); if (err < 0) { return ERR_NO_MEMORY; } LTRACEF("virtio_ring at pa 0x%lx\n", pa); #else void *vptr = memalign(PAGE_SIZE, size); if (!vptr) return ERR_NO_MEMORY; LTRACEF("ptr %p\n", vptr); memset(vptr, 0, size); /* compute the physical address */ paddr_t pa = (paddr_t)vptr; #endif /* initialize the ring */ vring_init(ring, len, vptr, PAGE_SIZE); dev->ring[index].free_list = 0xffff; dev->ring[index].free_count = 0; /* add all the descriptors to the free list */ for (uint i = 0; i < len; i++) { virtio_free_desc(dev, index, i); } /* register the ring with the device */ DEBUG_ASSERT(dev->mmio_config); dev->mmio_config->guest_page_size = PAGE_SIZE; dev->mmio_config->queue_sel = index; dev->mmio_config->queue_num = len; dev->mmio_config->queue_align = PAGE_SIZE; dev->mmio_config->queue_pfn = pa / PAGE_SIZE; /* mark the ring active */ dev->active_rings_bitmap |= (1 << index); return NO_ERROR; }
static int do_boot(lkb_t *lkb, size_t len, const char **result) { LTRACEF("lkb %p, len %zu, result %p\n", lkb, len, result); void *buf; paddr_t buf_phys; if (vmm_alloc_contiguous(vmm_get_kernel_aspace(), "lkboot_iobuf", len, &buf, log2_uint(1024*1024), 0, ARCH_MMU_FLAG_UNCACHED) < 0) { *result = "not enough memory"; return -1; } buf_phys = vaddr_to_paddr(buf); LTRACEF("iobuffer %p (phys 0x%lx)\n", buf, buf_phys); if (lkb_read(lkb, buf, len)) { *result = "io error"; // XXX free buffer here return -1; } /* construct a boot argument list */ const size_t bootargs_size = PAGE_SIZE; #if 0 void *args = (void *)((uintptr_t)lkb_iobuffer + lkb_iobuffer_size - bootargs_size); paddr_t args_phys = lkb_iobuffer_phys + lkb_iobuffer_size - bootargs_size; #elif PLATFORM_ZYNQ /* grab the top page of sram */ /* XXX do this better */ paddr_t args_phys = SRAM_BASE + SRAM_SIZE - bootargs_size; void *args = paddr_to_kvaddr(args_phys); #else #error need better way #endif LTRACEF("boot args %p, phys 0x%lx, len %zu\n", args, args_phys, bootargs_size); bootargs_start(args, bootargs_size); bootargs_add_command_line(args, bootargs_size, "what what"); arch_clean_cache_range((vaddr_t)args, bootargs_size); ulong lk_args[4]; bootargs_generate_lk_arg_values(args_phys, lk_args); const void *ptr; /* sniff it to see if it's a bootimage or a raw image */ bootimage_t *bi; if (bootimage_open(buf, len, &bi) >= 0) { size_t len; /* it's a bootimage */ TRACEF("detected bootimage\n"); /* find the lk image */ if (bootimage_get_file_section(bi, TYPE_LK, &ptr, &len) >= 0) { TRACEF("found lk section at %p\n", ptr); /* add the boot image to the argument list */ size_t bootimage_size; bootimage_get_range(bi, NULL, &bootimage_size); bootargs_add_bootimage_pointer(args, bootargs_size, "pmem", buf_phys, bootimage_size); } } else { /* raw image, just chain load it directly */ TRACEF("raw image, chainloading\n"); ptr = buf; } /* start a boot thread to complete the startup */ static struct chainload_args cl_args; cl_args.func = (void *)ptr; cl_args.args[0] = lk_args[0]; cl_args.args[1] = lk_args[1]; cl_args.args[2] = lk_args[2]; cl_args.args[3] = lk_args[3]; thread_resume(thread_create("boot", &chainload_thread, &cl_args, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE)); return 0; }