Example #1
0
File: q35.c Project: AlexHai/qemu
static AddressSpace *q35_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
{
    IntelIOMMUState *s = opaque;
    VTDAddressSpace **pvtd_as;
    int bus_num = pci_bus_num(bus);

    assert(0 <= bus_num && bus_num <= VTD_PCI_BUS_MAX);
    assert(0 <= devfn && devfn <= VTD_PCI_DEVFN_MAX);

    pvtd_as = s->address_spaces[bus_num];
    if (!pvtd_as) {
        /* No corresponding free() */
        pvtd_as = g_malloc0(sizeof(VTDAddressSpace *) * VTD_PCI_DEVFN_MAX);
        s->address_spaces[bus_num] = pvtd_as;
    }
    if (!pvtd_as[devfn]) {
        pvtd_as[devfn] = g_malloc0(sizeof(VTDAddressSpace));

        pvtd_as[devfn]->bus_num = (uint8_t)bus_num;
        pvtd_as[devfn]->devfn = (uint8_t)devfn;
        pvtd_as[devfn]->iommu_state = s;
        pvtd_as[devfn]->context_cache_entry.context_cache_gen = 0;
        memory_region_init_iommu(&pvtd_as[devfn]->iommu, OBJECT(s),
                                 &s->iommu_ops, "intel_iommu", UINT64_MAX);
        address_space_init(&pvtd_as[devfn]->as,
                           &pvtd_as[devfn]->iommu, "intel_iommu");
    }
    return &pvtd_as[devfn]->as;
}
Example #2
0
static void bcm2835_property_realize(DeviceState *dev, Error **errp)
{
    BCM2835PropertyState *s = BCM2835_PROPERTY(dev);
    Object *obj;
    Error *err = NULL;

    obj = object_property_get_link(OBJECT(dev), "fb", &err);
    if (obj == NULL) {
        error_setg(errp, "%s: required fb link not found: %s",
                   __func__, error_get_pretty(err));
        return;
    }

    s->fbdev = BCM2835_FB(obj);

    obj = object_property_get_link(OBJECT(dev), "dma-mr", &err);
    if (obj == NULL) {
        error_setg(errp, "%s: required dma-mr link not found: %s",
                   __func__, error_get_pretty(err));
        return;
    }

    s->dma_mr = MEMORY_REGION(obj);
    address_space_init(&s->dma_as, s->dma_mr, NULL);

    /* TODO: connect to MAC address of USB NIC device, once we emulate it */
    qemu_macaddr_default_if_unset(&s->macaddr);

    bcm2835_property_reset(dev);
}
Example #3
0
static void tz_ppc_realize(DeviceState *dev, Error **errp)
{
    Object *obj = OBJECT(dev);
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    TZPPC *s = TZ_PPC(dev);
    int i;

    /* We can't create the upstream end of the port until realize,
     * as we don't know the size of the MR used as the downstream until then.
     */
    for (i = 0; i < TZ_NUM_PORTS; i++) {
        TZPPCPort *port = &s->port[i];
        char *name;
        uint64_t size;

        if (!port->downstream) {
            continue;
        }

        name = g_strdup_printf("tz-ppc-port[%d]", i);

        port->ppc = s;
        address_space_init(&port->downstream_as, port->downstream, name);

        size = memory_region_size(port->downstream);
        memory_region_init_io(&port->upstream, obj, &tz_ppc_ops,
                              port, name, size);
        sysbus_init_mmio(sbd, &port->upstream);
        g_free(name);
    }
}
Example #4
0
static void pnv_lpc_realize(DeviceState *dev, Error **errp)
{
    PnvLpcController *lpc = PNV_LPC(dev);
    Object *obj;
    Error *error = NULL;

    /* Reg inits */
    lpc->lpc_hc_fw_rd_acc_size = LPC_HC_FW_RD_4B;

    /* Create address space and backing MR for the OPB bus */
    memory_region_init(&lpc->opb_mr, OBJECT(dev), "lpc-opb", 0x100000000ull);
    address_space_init(&lpc->opb_as, &lpc->opb_mr, "lpc-opb");

    /* Create ISA IO and Mem space regions which are the root of
     * the ISA bus (ie, ISA address spaces). We don't create a
     * separate one for FW which we alias to memory.
     */
    memory_region_init(&lpc->isa_io, OBJECT(dev), "isa-io", ISA_IO_SIZE);
    memory_region_init(&lpc->isa_mem, OBJECT(dev), "isa-mem", ISA_MEM_SIZE);
    memory_region_init(&lpc->isa_fw, OBJECT(dev),  "isa-fw", ISA_FW_SIZE);

    /* Create windows from the OPB space to the ISA space */
    memory_region_init_alias(&lpc->opb_isa_io, OBJECT(dev), "lpc-isa-io",
                             &lpc->isa_io, 0, LPC_IO_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_IO_OPB_ADDR,
                                &lpc->opb_isa_io);
    memory_region_init_alias(&lpc->opb_isa_mem, OBJECT(dev), "lpc-isa-mem",
                             &lpc->isa_mem, 0, LPC_MEM_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_MEM_OPB_ADDR,
                                &lpc->opb_isa_mem);
    memory_region_init_alias(&lpc->opb_isa_fw, OBJECT(dev), "lpc-isa-fw",
                             &lpc->isa_fw, 0, LPC_FW_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_FW_OPB_ADDR,
                                &lpc->opb_isa_fw);

    /* Create MMIO regions for LPC HC and OPB registers */
    memory_region_init_io(&lpc->opb_master_regs, OBJECT(dev), &opb_master_ops,
                          lpc, "lpc-opb-master", LPC_OPB_REGS_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_OPB_REGS_OPB_ADDR,
                                &lpc->opb_master_regs);
    memory_region_init_io(&lpc->lpc_hc_regs, OBJECT(dev), &lpc_hc_ops, lpc,
                          "lpc-hc", LPC_HC_REGS_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_HC_REGS_OPB_ADDR,
                                &lpc->lpc_hc_regs);

    /* XScom region for LPC registers */
    pnv_xscom_region_init(&lpc->xscom_regs, OBJECT(dev),
                          &pnv_lpc_xscom_ops, lpc, "xscom-lpc",
                          PNV_XSCOM_LPC_SIZE);

    /* get PSI object from chip */
    obj = object_property_get_link(OBJECT(dev), "psi", &error);
    if (!obj) {
        error_setg(errp, "%s: required link 'psi' not found: %s",
                   __func__, error_get_pretty(error));
        return;
    }
    lpc->psi = PNV_PSI(obj);
}
Example #5
0
File: auxbus.c Project: 8tab/qemu
AUXBus *aux_init_bus(DeviceState *parent, const char *name)
{
    AUXBus *bus;

    bus = AUX_BUS(qbus_create(TYPE_AUX_BUS, parent, name));
    bus->bridge = AUXTOI2C(qdev_create(BUS(bus), TYPE_AUXTOI2C));

    /* Memory related. */
    bus->aux_io = g_malloc(sizeof(*bus->aux_io));
    memory_region_init(bus->aux_io, OBJECT(bus), "aux-io", (1 << 20));
    address_space_init(&bus->aux_addr_space, bus->aux_io, "aux-io");
    return bus;
}
Example #6
0
static void pnv_lpc_realize(DeviceState *dev, Error **errp)
{
    PnvLpcController *lpc = PNV_LPC(dev);

    /* Reg inits */
    lpc->lpc_hc_fw_rd_acc_size = LPC_HC_FW_RD_4B;

    /* Create address space and backing MR for the OPB bus */
    memory_region_init(&lpc->opb_mr, OBJECT(dev), "lpc-opb", 0x100000000ull);
    address_space_init(&lpc->opb_as, &lpc->opb_mr, "lpc-opb");

    /* Create ISA IO and Mem space regions which are the root of
     * the ISA bus (ie, ISA address spaces). We don't create a
     * separate one for FW which we alias to memory.
     */
    memory_region_init(&lpc->isa_io, OBJECT(dev), "isa-io", ISA_IO_SIZE);
    memory_region_init(&lpc->isa_mem, OBJECT(dev), "isa-mem", ISA_MEM_SIZE);

    /* Create windows from the OPB space to the ISA space */
    memory_region_init_alias(&lpc->opb_isa_io, OBJECT(dev), "lpc-isa-io",
                             &lpc->isa_io, 0, LPC_IO_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_IO_OPB_ADDR,
                                &lpc->opb_isa_io);
    memory_region_init_alias(&lpc->opb_isa_mem, OBJECT(dev), "lpc-isa-mem",
                             &lpc->isa_mem, 0, LPC_MEM_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_MEM_OPB_ADDR,
                                &lpc->opb_isa_mem);
    memory_region_init_alias(&lpc->opb_isa_fw, OBJECT(dev), "lpc-isa-fw",
                             &lpc->isa_mem, 0, LPC_FW_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_FW_OPB_ADDR,
                                &lpc->opb_isa_fw);

    /* Create MMIO regions for LPC HC and OPB registers */
    memory_region_init_io(&lpc->opb_master_regs, OBJECT(dev), &opb_master_ops,
                          lpc, "lpc-opb-master", LPC_OPB_REGS_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_OPB_REGS_OPB_ADDR,
                                &lpc->opb_master_regs);
    memory_region_init_io(&lpc->lpc_hc_regs, OBJECT(dev), &lpc_hc_ops, lpc,
                          "lpc-hc", LPC_HC_REGS_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_HC_REGS_OPB_ADDR,
                                &lpc->lpc_hc_regs);

    /* XScom region for LPC registers */
    pnv_xscom_region_init(&lpc->xscom_regs, OBJECT(dev),
                          &pnv_lpc_xscom_ops, lpc, "xscom-lpc",
                          PNV_XSCOM_LPC_SIZE);
}
Example #7
0
static void bcm2835_mbox_realize(DeviceState *dev, Error **errp)
{
    BCM2835MboxState *s = BCM2835_MBOX(dev);
    Object *obj;
    Error *err = NULL;

    obj = object_property_get_link(OBJECT(dev), "mbox-mr", &err);
    if (obj == NULL) {
        error_setg(errp, "%s: required mbox-mr link not found: %s",
                   __func__, error_get_pretty(err));
        return;
    }

    s->mbox_mr = MEMORY_REGION(obj);
    address_space_init(&s->mbox_as, s->mbox_mr, NULL);
    bcm2835_mbox_reset(dev);
}
Example #8
0
static void xtensa_cpu_initfn(Object *obj)
{
    CPUState *cs = CPU(obj);
    XtensaCPU *cpu = XTENSA_CPU(obj);
    XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(obj);
    CPUXtensaState *env = &cpu->env;

    cs->env_ptr = env;
    env->config = xcc->config;

#ifndef CONFIG_USER_ONLY
    env->address_space_er = g_malloc(sizeof(*env->address_space_er));
    env->system_er = g_malloc(sizeof(*env->system_er));
    memory_region_init_io(env->system_er, NULL, NULL, env, "er",
                          UINT64_C(0x100000000));
    address_space_init(env->address_space_er, env->system_er, "ER");
#endif
}
Example #9
0
static int ppc440_pcix_initfn(SysBusDevice *dev)
{
    PPC440PCIXState *s;
    PCIHostState *h;
    int i;

    h = PCI_HOST_BRIDGE(dev);
    s = PPC440_PCIX_HOST_BRIDGE(dev);

    for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
        sysbus_init_irq(dev, &s->irq[i]);
    }

    memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX);
    h->bus = pci_register_root_bus(DEVICE(dev), NULL, ppc440_pcix_set_irq,
                         ppc440_pcix_map_irq, s->irq, &s->busmem,
                         get_system_io(), PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);

    s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge");

    memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX);
    memory_region_add_subregion(&s->bm, 0x0, &s->busmem);
    address_space_init(&s->bm_as, &s->bm, "pci-bm");
    pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s);

    memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE);
    memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops,
                          h, "pci-conf-idx", 4);
    memory_region_init_io(&h->data_mem, OBJECT(s), &ppc440_pcix_host_data_ops,
                          h, "pci-conf-data", 4);
    memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s,
                          "pci.reg", PPC440_REG_SIZE);
    memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem);
    memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem);
    memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem);
    sysbus_init_mmio(dev, &s->container);

    return 0;
}
Example #10
0
static void dp8393x_realize(DeviceState *dev, Error **errp)
{
    dp8393xState *s = DP8393X(dev);
    int i, checksum;
    uint8_t *prom;
    Error *local_err = NULL;

    address_space_init(&s->as, s->dma_mr, "dp8393x");
    memory_region_init_io(&s->mmio, OBJECT(dev), &dp8393x_ops, s,
                          "dp8393x-regs", 0x40 << s->it_shift);

    s->nic = qemu_new_nic(&net_dp83932_info, &s->conf,
                          object_get_typename(OBJECT(dev)), dev->id, s);
    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);

    s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s);
    s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */

    memory_region_init_ram(&s->prom, OBJECT(dev),
                           "dp8393x-prom", SONIC_PROM_SIZE, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
    memory_region_set_readonly(&s->prom, true);
    prom = memory_region_get_ram_ptr(&s->prom);
    checksum = 0;
    for (i = 0; i < 6; i++) {
        prom[i] = s->conf.macaddr.a[i];
        checksum += prom[i];
        if (checksum > 0xff) {
            checksum = (checksum + 1) & 0xff;
        }
    }
    prom[7] = 0xff - checksum;
}
Example #11
0
PCIBus *dino_init(MemoryRegion *addr_space,
                  qemu_irq *p_rtc_irq, qemu_irq *p_ser_irq)
{
    DeviceState *dev;
    DinoState *s;
    PCIBus *b;
    int i;

    dev = qdev_create(NULL, TYPE_DINO_PCI_HOST_BRIDGE);
    s = DINO_PCI_HOST_BRIDGE(dev);

    /* Dino PCI access from main memory.  */
    memory_region_init_io(&s->this_mem, OBJECT(s), &dino_chip_ops,
                          s, "dino", 4096);
    memory_region_add_subregion(addr_space, DINO_HPA, &s->this_mem);

    /* Dino PCI config. */
    memory_region_init_io(&s->parent_obj.conf_mem, OBJECT(&s->parent_obj),
                          &pci_host_conf_be_ops, dev, "pci-conf-idx", 4);
    memory_region_init_io(&s->parent_obj.data_mem, OBJECT(&s->parent_obj),
                          &dino_config_data_ops, dev, "pci-conf-data", 4);
    memory_region_add_subregion(&s->this_mem, DINO_PCI_CONFIG_ADDR,
                                &s->parent_obj.conf_mem);
    memory_region_add_subregion(&s->this_mem, DINO_CONFIG_DATA,
                                &s->parent_obj.data_mem);

    /* Dino PCI bus memory.  */
    memory_region_init(&s->pci_mem, OBJECT(s), "pci-memory", 1ull << 32);

    b = pci_register_root_bus(dev, "pci", dino_set_irq, dino_pci_map_irq, s,
                              &s->pci_mem, get_system_io(),
                              PCI_DEVFN(0, 0), 32, TYPE_PCI_BUS);
    s->parent_obj.bus = b;
    qdev_init_nofail(dev);

    /* Set up windows into PCI bus memory.  */
    for (i = 1; i < 31; i++) {
        uint32_t addr = 0xf0000000 + i * DINO_MEM_CHUNK_SIZE;
        char *name = g_strdup_printf("PCI Outbound Window %d", i);
        memory_region_init_alias(&s->pci_mem_alias[i], OBJECT(s),
                                 name, &s->pci_mem, addr,
                                 DINO_MEM_CHUNK_SIZE);
    }

    /* Set up PCI view of memory: Bus master address space.  */
    memory_region_init(&s->bm, OBJECT(s), "bm-dino", 1ull << 32);
    memory_region_init_alias(&s->bm_ram_alias, OBJECT(s),
                             "bm-system", addr_space, 0,
                             0xf0000000 + DINO_MEM_CHUNK_SIZE);
    memory_region_init_alias(&s->bm_pci_alias, OBJECT(s),
                             "bm-pci", &s->pci_mem,
                             0xf0000000 + DINO_MEM_CHUNK_SIZE,
                             30 * DINO_MEM_CHUNK_SIZE);
    memory_region_init_alias(&s->bm_cpu_alias, OBJECT(s),
                             "bm-cpu", addr_space, 0xfff00000,
                             0xfffff);
    memory_region_add_subregion(&s->bm, 0,
                                &s->bm_ram_alias);
    memory_region_add_subregion(&s->bm,
                                0xf0000000 + DINO_MEM_CHUNK_SIZE,
                                &s->bm_pci_alias);
    memory_region_add_subregion(&s->bm, 0xfff00000,
                                &s->bm_cpu_alias);
    address_space_init(&s->bm_as, &s->bm, "pci-bm");
    pci_setup_iommu(b, dino_pcihost_set_iommu, s);

    *p_rtc_irq = qemu_allocate_irq(dino_set_timer_irq, s, 0);
    *p_ser_irq = qemu_allocate_irq(dino_set_serial_irq, s, 0);

    return b;
}
Example #12
0
static int load_bin_elf(struct exe_params *params, struct irq_frame *frame)
{
    struct elf_header head;
    struct elf_prog_section sect;
    int ret, i;
    off_t current_off;
    struct address_space *new_addrspc;
    struct task *current;

    ret = vfs_read(params->exe, &head, sizeof(head));
    if (ret != sizeof(head))
        return -ENOEXEC;

    if (head.magic != ELF_MAGIC)
        return -ENOEXEC;

    new_addrspc = kmalloc(sizeof(*new_addrspc), PAL_KERNEL);
    address_space_init(new_addrspc);

    kp(KP_TRACE, "Parsing ELF binary... frame: %p, state: %d\n", frame, cpu_get_local()->current->state);

    /* The idea is that you loop over every header, and if a header's type is
     * 'LOAD' then we make a vm_map for it and load it into memory. */
    for (i = 0, current_off = head.prog_head_pos; i < head.prog_head_count; i++, current_off += sizeof(struct elf_prog_section)) {

        kp(KP_TRACE, "Reading ELF section...\n");
        vfs_lseek(params->exe, current_off, SEEK_SET);
        ret = vfs_read(params->exe, &sect, sizeof(sect));
        kp(KP_TRACE, "Reading ret: %d\n", ret);
        if (ret != sizeof(sect))
            return -ENOEXEC;

        if (sect.type != ELF_PROG_TYPE_LOAD)
            continue;

        kp(KP_TRACE, "Creating new vm_map...\n");
        struct vm_map *new_sect = kmalloc(sizeof(struct vm_map), PAL_KERNEL);
        vm_map_init(new_sect);

        new_sect->addr.start = va_make(sect.vaddr);
        new_sect->addr.end = va_make(sect.vaddr + sect.mem_size);

        if (sect.flags & ELF_PROG_FLAG_EXEC)
            flag_set(&new_sect->flags, VM_MAP_EXE);

        if (sect.flags & ELF_PROG_FLAG_READ)
            flag_set(&new_sect->flags, VM_MAP_READ);

        if (sect.flags & ELF_PROG_FLAG_WRITE)
            flag_set(&new_sect->flags, VM_MAP_WRITE);

        kp(KP_TRACE, "Map from %p to %p\n", new_sect->addr.start, new_sect->addr.end);

        if (!new_addrspc->code)
            new_addrspc->code = new_sect;
        else if (new_addrspc->code->addr.start > new_sect->addr.start)
            new_addrspc->code = new_sect;

        if (!new_addrspc->data)
            new_addrspc->data = new_sect;
        else if (new_addrspc->data->addr.start < new_sect->addr.start)
            new_addrspc->data = new_sect;

        /* f_size is the size in the file, mem_size is the size in memory of
         * our copy.
         *
         * If mem_size > f_size, then the empty space is filled with zeros. */
        int pages = PG_ALIGN(sect.mem_size) / PG_SIZE;
        int k;
        off_t starting_offset = sect.f_off - PG_ALIGN_DOWN(sect.f_off);
        off_t file_size = sect.f_size + starting_offset;
        off_t file_offset = sect.f_off - starting_offset;

        kp(KP_TRACE,"Starting_offset: %ld\n", starting_offset);

        /* This could be cleaned-up. The complexity comes from the fact that
         * sect.f_off doesn't have to be page aligned, even if the section it
         * is in has to be page aligned - This is more then likely due to
         * sections being stripped out, leaving the other sections at odd offsets.
         *
         * Thus, we handle the first page separate from the rest of the pages,
         * and handle it's offset into virtual memory manually. Then, we loop
         * to handle the rest of the pages, using 'file_size' and 'file_offset'
         * which are adjusted values to skip the first part of the file that we
         * already read.
         */

        for (k = 0; k < pages; k++) {
            off_t len;
            struct page *p = palloc(0, PAL_KERNEL);

            if (PG_SIZE * k + PG_SIZE < file_size)
                len = PG_SIZE - starting_offset;
            else if (file_size > PG_SIZE * k)
                len = file_size - starting_offset - PG_SIZE * k;
            else
                len = 0;

            if (len) {
                vfs_lseek(params->exe, file_offset + starting_offset + (k * PG_SIZE), SEEK_SET);
                vfs_read(params->exe, p->virt + starting_offset, len);
            }

            len += starting_offset;
            starting_offset = 0;

            if (len < PG_SIZE)
                memset(p->virt + len, 0, PG_SIZE - len);

            starting_offset = 0;

            list_add_tail(&new_sect->page_list, &p->page_list_node);
        }

        address_space_vm_map_add(new_addrspc, new_sect);
    }

    /* If we detected both the code and data segments to be the same segment,
     * then that means we don't actually have a data segment, so we set it to
     * NULL. This only actually matters for setting the BRK, and we'll just
     * make a new vm_map if the data is NULL in that case. */
    if (new_addrspc->code == new_addrspc->data)
        new_addrspc->data = NULL;

    struct vm_map *stack = kmalloc(sizeof(struct vm_map), PAL_KERNEL);
    vm_map_init(stack);

    stack->addr.end = KMEM_PROG_STACK_END;
    stack->addr.start = KMEM_PROG_STACK_START;

    flag_set(&stack->flags, VM_MAP_READ);
    flag_set(&stack->flags, VM_MAP_WRITE);
    flag_set(&stack->flags, VM_MAP_EXE);

    palloc_unordered(&stack->page_list, KMEM_STACK_LIMIT, PAL_KERNEL);

    address_space_vm_map_add(new_addrspc, stack);

    new_addrspc->stack = stack;

    kp(KP_TRACE, "New code segment: %p-%p\n", new_addrspc->code->addr.start, new_addrspc->code->addr.end);
    if (new_addrspc->data)
        kp(KP_TRACE, "New data segment: %p-%p\n", new_addrspc->data->addr.start, new_addrspc->data->addr.end);
    kp(KP_TRACE, "New stack segment: %p-%p\n", new_addrspc->stack->addr.start, new_addrspc->stack->addr.end);

    current = cpu_get_local()->current;

    arch_task_change_address_space(new_addrspc);

    irq_frame_initalize(current->context.frame);

    irq_frame_set_stack(current->context.frame, new_addrspc->stack->addr.end);
    irq_frame_set_ip(current->context.frame, va_make(head.entry_vaddr));

    return 0;
}
Example #13
0
/* Called from RCU critical section */
static IOMMUTLBEntry sun4m_translate_iommu(IOMMUMemoryRegion *iommu,
                                           hwaddr addr,
                                           IOMMUAccessFlags flags)
{
    IOMMUState *is = container_of(iommu, IOMMUState, iommu);
    hwaddr page, pa;
    int is_write = (flags & IOMMU_WO) ? 1 : 0;
    uint32_t pte;
    IOMMUTLBEntry ret = {
        .target_as = &address_space_memory,
        .iova = 0,
        .translated_addr = 0,
        .addr_mask = ~(hwaddr)0,
        .perm = IOMMU_NONE,
    };

    page = addr & IOMMU_PAGE_MASK;
    pte = iommu_page_get_flags(is, page);
    if (!(pte & IOPTE_VALID)) {
        iommu_bad_addr(is, page, is_write);
        return ret;
    }

    pa = iommu_translate_pa(addr, pte);
    if (is_write && !(pte & IOPTE_WRITE)) {
        iommu_bad_addr(is, page, is_write);
        return ret;
    }

    if (pte & IOPTE_WRITE) {
        ret.perm = IOMMU_RW;
    } else {
        ret.perm = IOMMU_RO;
    }

    ret.iova = page;
    ret.translated_addr = pa;
    ret.addr_mask = ~IOMMU_PAGE_MASK;

    return ret;
}

static const VMStateDescription vmstate_iommu = {
    .name ="iommu",
    .version_id = 2,
    .minimum_version_id = 2,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32_ARRAY(regs, IOMMUState, IOMMU_NREGS),
        VMSTATE_UINT64(iostart, IOMMUState),
        VMSTATE_END_OF_LIST()
    }
};

static void iommu_reset(DeviceState *d)
{
    IOMMUState *s = SUN4M_IOMMU(d);

    memset(s->regs, 0, IOMMU_NREGS * 4);
    s->iostart = 0;
    s->regs[IOMMU_CTRL] = s->version;
    s->regs[IOMMU_ARBEN] = IOMMU_MID;
    s->regs[IOMMU_AFSR] = IOMMU_AFSR_RESV;
    s->regs[IOMMU_AER] = IOMMU_AER_EN_P0_ARB | IOMMU_AER_EN_P1_ARB;
    s->regs[IOMMU_MASK_ID] = IOMMU_TS_MASK;
}

static void iommu_init(Object *obj)
{
    IOMMUState *s = SUN4M_IOMMU(obj);
    SysBusDevice *dev = SYS_BUS_DEVICE(obj);

    memory_region_init_iommu(&s->iommu, sizeof(s->iommu),
                             TYPE_SUN4M_IOMMU_MEMORY_REGION, OBJECT(dev),
                             "iommu-sun4m", UINT64_MAX);
    address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu), "iommu-as");

    sysbus_init_irq(dev, &s->irq);

    memory_region_init_io(&s->iomem, obj, &iommu_mem_ops, s, "iommu",
                          IOMMU_NREGS * sizeof(uint32_t));
    sysbus_init_mmio(dev, &s->iomem);
}