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; }
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); }
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); } }
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); }
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; }
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); }
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); }
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 }
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; }
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; }
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; }
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, §, 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; }
/* 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); }