Ejemplo n.º 1
0
status_t virtio_gpu_init(struct virtio_device *dev, uint32_t host_features)
{
    LTRACEF("dev %p, host_features 0x%x\n", dev, host_features);

    /* allocate a new gpu device */
    struct virtio_gpu_dev *gdev = malloc(sizeof(struct virtio_gpu_dev));
    if (!gdev)
        return ERR_NO_MEMORY;

    mutex_init(&gdev->lock);
    event_init(&gdev->io_event, false, EVENT_FLAG_AUTOUNSIGNAL);
    event_init(&gdev->flush_event, false, EVENT_FLAG_AUTOUNSIGNAL);

    gdev->dev = dev;
    dev->priv = gdev;

    gdev->pmode_id = -1;
    gdev->next_resource_id = 1;

    /* allocate memory for a gpu request */
#if WITH_KERNEL_VM
    gdev->gpu_request = pmm_alloc_kpage();
    gdev->gpu_request_phys = vaddr_to_paddr(gdev->gpu_request);
#else
    gdev->gpu_request = malloc(sizeof(struct virtio_gpu_resp_display_info)); // XXX get size better
    gdev->gpu_request_phys = (paddr_t)gdev->gpu_request;
#endif

    /* make sure the device is reset */
    virtio_reset_device(dev);

    volatile struct virtio_gpu_config *config = (struct virtio_gpu_config *)dev->config_ptr;
    dump_gpu_config(config);

    /* ack and set the driver status bit */
    virtio_status_acknowledge_driver(dev);

    // XXX check features bits and ack/nak them

    /* allocate a virtio ring */
    virtio_alloc_ring(dev, 0, 16);

    /* set our irq handler */
    dev->irq_driver_callback = &virtio_gpu_irq_driver_callback;
    dev->config_change_callback = &virtio_gpu_config_change_callback;

    /* set DRIVER_OK */
    virtio_status_driver_ok(dev);

    /* save the main device we've found */
    the_gdev = gdev;

    printf("found virtio gpu device\n");

    return NO_ERROR;
}
Ejemplo n.º 2
0
Archivo: mmu.c Proyecto: chenyuwen/lk
status_t arch_mmu_init_aspace(arch_aspace_t *aspace, vaddr_t base, size_t size, uint flags)
{
    LTRACEF("aspace %p, base 0x%lx, size 0x%zx, flags 0x%x\n", aspace, base, size, flags);

    DEBUG_ASSERT(aspace);

    /* validate that the base + size is sane and doesn't wrap */
    DEBUG_ASSERT(size > PAGE_SIZE);
    DEBUG_ASSERT(base + size - 1 > base);

    list_initialize(&aspace->pt_page_list);

    if (flags & ARCH_ASPACE_FLAG_KERNEL) {
        aspace->base = base;
        aspace->size = size;
        aspace->tt_virt = arm_kernel_translation_table;
        aspace->tt_phys = vaddr_to_paddr(aspace->tt_virt);
    } else {

        // XXX at the moment we can only really deal with 1GB user space, and thus
        // needing only a single page for the top level translation table
        DEBUG_ASSERT(base < GB && (base + size) <= GB);

        aspace->base = base;
        aspace->size = size;

        uint32_t *va = pmm_alloc_kpages(1, &aspace->pt_page_list);
        if (!va)
            return ERR_NO_MEMORY;

        aspace->tt_virt = va;
        aspace->tt_phys = vaddr_to_paddr(aspace->tt_virt);
    }

    LTRACEF("tt_phys 0x%lx tt_virt %p\n", aspace->tt_phys, aspace->tt_virt);

    return NO_ERROR;
}
Ejemplo n.º 3
0
static status_t attach_backing(struct virtio_gpu_dev *gdev, uint32_t resource_id, void *ptr, size_t buf_len)
{
    status_t err;

    LTRACEF("gdev %p, resource_id %u, ptr %p, buf_len %zu\n", gdev, resource_id, ptr, buf_len);

    DEBUG_ASSERT(gdev);
    DEBUG_ASSERT(ptr);

    /* grab a lock to keep this single message at a time */
    mutex_acquire(&gdev->lock);

    /* construct the request */
    struct {
        struct virtio_gpu_resource_attach_backing req;
        struct virtio_gpu_mem_entry mem;
    } req;
    memset(&req, 0, sizeof(req));

    req.req.hdr.type = VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING;
    req.req.resource_id = resource_id;
    req.req.nr_entries = 1;

    paddr_t pa;
    pa = vaddr_to_paddr(ptr);
    req.mem.addr = pa;
    req.mem.length = buf_len;

    /* send the command and get a response */
    struct virtio_gpu_ctrl_hdr *res;
    err = send_command_response(gdev, &req, sizeof(req), (void **)&res, sizeof(*res));
    DEBUG_ASSERT(err == NO_ERROR);

    /* see if we got a valid response */
    LTRACEF("response type 0x%x\n", res->type);
    err = (res->type == VIRTIO_GPU_RESP_OK_NODATA) ? NO_ERROR : ERR_NO_MEMORY;

    /* release the lock */
    mutex_release(&gdev->lock);

    return err;
}
Ejemplo n.º 4
0
Archivo: vm.c Proyecto: Kloniks/muk
static void test_identity_zone(void)
{
  uint32_t i;
  uint32_t count;
  paddr_t paddr;
  vm_as_t* as;

  as = vm_get_kernel_as();

  count = phys_get_mem_size();
  for (i = 0; i < count; ++i)
    {
      paddr = vaddr_to_paddr(as, (vaddr_t)i);
      if (paddr != NULL)
	  {
	    if (*(uint8_t*)paddr != ((uint8_t*)as->identity)[i])
	      serial_printl("[!] error @ 0x%x\n", i);
	  }
    }
}
Ejemplo n.º 5
0
static int cmd_display_mem(int argc, const cmd_args *argv, uint32_t flags) {
    /* save the last address and len so we can continue where we left off */
    static unsigned long address;
    static size_t len;

    if (argc < 3 && len == 0) {
        printf("not enough arguments\n");
        printf("%s [-l] [-b] [address] [length]\n", argv[0].str);
        return -1;
    }

    int size;
    if (strcmp(argv[0].str, "dw") == 0) {
        size = 4;
    } else if (strcmp(argv[0].str, "dh") == 0) {
        size = 2;
    } else {
        size = 1;
    }

    uint byte_order = BYTE_ORDER;
    int argindex = 1;
    bool read_address = false;
    while (argc > argindex) {
        if (!strcmp(argv[argindex].str, "-l")) {
            byte_order = LITTLE_ENDIAN;
        } else if (!strcmp(argv[argindex].str, "-b")) {
            byte_order = BIG_ENDIAN;
        } else if (!read_address) {
            address = argv[argindex].u;
            read_address = true;
        } else {
            len = argv[argindex].u;
        }

        argindex++;
    }

    unsigned long stop = address + len;
    int count = 0;

    if ((address & (size - 1)) != 0) {
        printf("unaligned address, cannot display\n");
        return -1;
    }

    /* preflight the start address to see if it's mapped */
    if (vaddr_to_paddr((void *)address) == 0) {
        printf("ERROR: address 0x%lx is unmapped\n", address);
        return -1;
    }

    for ( ; address < stop; address += size) {
        if (count == 0)
            printf("0x%08lx: ", address);
        switch (size) {
            case 4: {
                uint32_t val = (byte_order != BYTE_ORDER) ?
                               SWAP_32(*(uint32_t *)address) :
                               *(uint32_t *)address;
                printf("%08x ", val);
                break;
            }
            case 2: {
                uint16_t val = (byte_order != BYTE_ORDER) ?
                               SWAP_16(*(uint16_t *)address) :
                               *(uint16_t *)address;
                printf("%04hx ", val);
                break;
            }
            case 1:
                printf("%02hhx ", *(uint8_t *)address);
                break;
        }
        count += size;
        if (count == 16) {
            printf("\n");
            count = 0;
        }
    }

    if (count != 0)
        printf("\n");

    return 0;
}
Ejemplo n.º 6
0
// return NULL for success, error string for failure
int lkb_handle_command(lkb_t *lkb, const char *cmd, const char *arg, size_t len, const char **result)
{
    *result = NULL;

    struct lkb_command *lcmd;
    for (lcmd = lkb_cmd_list; lcmd; lcmd = lcmd->next) {
        if (!strcmp(lcmd->name, cmd)) {
            *result = lcmd->handler(lkb, arg, len, lcmd->cookie);
            return 0;
        }
    }

    if (!strcmp(cmd, "flash") || !strcmp(cmd, "erase")) {
        struct ptable_entry entry;
        bdev_t *bdev;

        if (ptable_find(arg, &entry) < 0) {
            size_t plen = len;
            /* doesn't exist, make one */
            if (ptable_add(arg, plen, 0) < 0) {
                *result = "error creating partition";
                return -1;
            }

            if (ptable_find(arg, &entry) < 0) {
                *result = "couldn't find partition after creating it";
                return -1;
            }
        }
        if (len > entry.length) {
            *result = "partition too small";
            return -1;
        }

        if (!(bdev = ptable_get_device())) {
            *result = "ptable_get_device failed";
            return -1;
        }

        printf("lkboot: erasing partition of size %llu\n", entry.length);
        if (bio_erase(bdev, entry.offset, entry.length) != (ssize_t)entry.length) {
            *result = "bio_erase failed";
            return -1;
        }

        if (!strcmp(cmd, "flash")) {
            printf("lkboot: writing to partition\n");

            void *buf = malloc(bdev->block_size);
            if (!buf) {
                *result = "memory allocation failed";
                return -1;
            }

            size_t pos = 0;
            while (pos < len) {
                size_t toread = MIN(len - pos, bdev->block_size);

                LTRACEF("offset %zu, toread %zu\n", pos, toread);

                if (lkb_read(lkb, buf, toread)) {
                    *result = "io error";
                    free(buf);
                    return -1;
                }

                if (bio_write(bdev, buf, entry.offset + pos, toread) != (ssize_t)toread) {
                    *result = "bio_write failed";
                    free(buf);
                    return -1;
                }

                pos += toread;
            }

            free(buf);
        }
    } else if (!strcmp(cmd, "remove")) {
        if (ptable_remove(arg) < 0) {
            *result = "remove failed";
            return -1;
        }
    } else if (!strcmp(cmd, "fpga")) {
#if PLATFORM_ZYNQ
        void *buf = malloc(len);
        if (!buf) {
            *result = "error allocating buffer";
            return -1;
        }

        /* translate to physical address */
        paddr_t pa = vaddr_to_paddr(buf);
        if (pa == 0) {
            *result = "error allocating buffer";
            free(buf);
            return -1;

        }

        if (lkb_read(lkb, buf, len)) {
            *result = "io error";
            free(buf);
            return -1;
        }

        /* make sure the cache is flushed for this buffer for DMA coherency purposes */
        arch_clean_cache_range((vaddr_t)buf, len);

        /* program the fpga */
        zynq_reset_fpga();
        zynq_program_fpga(pa, len);

        free(buf);
#else
        *result = "no fpga";
        return -1;
#endif
    } else if (!strcmp(cmd, "boot")) {
        return do_boot(lkb, len, result);
    } else if (!strcmp(cmd, "getsysparam")) {
        const void *ptr;
        size_t len;
        if (sysparam_get_ptr(arg, &ptr, &len) == 0) {
            lkb_write(lkb, ptr, len);
        }
    } else if (!strcmp(cmd, "reboot")) {
        thread_resume(thread_create("reboot", &do_reboot, NULL,
            DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
    } else {
        *result = "unknown command";
        return -1;
    }

    return 0;
}
Ejemplo n.º 7
0
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;
}