#define IOMMU_CTRL_TSB_SHIFT 16
#define IOMMU_BASE 0x8
+#define IOMMU_FLUSH 0x10
#define IOMMU_TTE_DATA_V (1ULL << 63)
#define IOMMU_TTE_DATA_SIZE (1ULL << 61)
#define IOMMU_TTE_DATA_W (1ULL << 1)
-#define IOMMU_TTE_PHYS_MASK_8K 0x1ffffffe000
-#define IOMMU_TTE_PHYS_MASK_64K 0x1ffffff8000
+#define IOMMU_TTE_PHYS_MASK_8K 0x1ffffffe000ULL
+#define IOMMU_TTE_PHYS_MASK_64K 0x1ffffff8000ULL
#define IOMMU_TSB_8K_OFFSET_MASK_8M 0x00000000007fe000ULL
#define IOMMU_TSB_8K_OFFSET_MASK_16M 0x0000000000ffe000ULL
IOMMUState iommu;
uint32_t pci_control[16];
uint32_t pci_irq_map[8];
+ uint32_t pci_err_irq_map[4];
uint32_t obio_irq_map[32];
qemu_irq *pbm_irqs;
qemu_irq *ivec_irqs;
return &is->iommu_as;
}
-static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr)
+static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr,
+ bool is_write)
{
IOMMUState *is = container_of(iommu, IOMMUState, iommu);
hwaddr baseaddr, offset;
is->regs[IOMMU_CTRL >> 3] &= 0xffffffffULL;
is->regs[IOMMU_CTRL >> 3] |= val << 32;
} else {
- is->regs[IOMMU_CTRL] = val;
+ is->regs[IOMMU_CTRL >> 3] = val;
}
break;
case IOMMU_CTRL + 0x4:
is->regs[IOMMU_BASE >> 3] &= 0xffffffffULL;
is->regs[IOMMU_BASE >> 3] |= val << 32;
} else {
- is->regs[IOMMU_BASE] = val;
+ is->regs[IOMMU_BASE >> 3] = val;
}
break;
case IOMMU_BASE + 0x4:
is->regs[IOMMU_BASE >> 3] &= 0xffffffff00000000ULL;
is->regs[IOMMU_BASE >> 3] |= val & 0xffffffffULL;
break;
+ case IOMMU_FLUSH:
+ case IOMMU_FLUSH + 0x4:
+ break;
default:
qemu_log_mask(LOG_UNIMP,
"apb iommu: Unimplemented register write "
case IOMMU_BASE + 0x4:
val = is->regs[IOMMU_BASE >> 3] & 0xffffffffULL;
break;
+ case IOMMU_FLUSH:
+ case IOMMU_FLUSH + 0x4:
+ val = 0;
+ break;
default:
qemu_log_mask(LOG_UNIMP,
"apb iommu: Unimplemented register read "
/* XXX: not implemented yet */
break;
case 0x200 ... 0x217: /* IOMMU */
- iommu_config_write(is, (addr & 0xf), val, size);
+ iommu_config_write(is, (addr & 0x1f), val, size);
break;
case 0xc00 ... 0xc3f: /* PCI interrupt control */
if (addr & 4) {
pbm_check_irqs(s);
}
break;
- case 0x1000 ... 0x1080: /* OBIO interrupt control */
+ case 0x1000 ... 0x107f: /* OBIO interrupt control */
if (addr & 4) {
unsigned int ino = ((addr & 0xff) >> 3);
s->obio_irq_map[ino] &= PBM_PCI_IMR_MASK;
/* XXX: not implemented yet */
break;
case 0x200 ... 0x217: /* IOMMU */
- val = iommu_config_read(is, (addr & 0xf), size);
+ val = iommu_config_read(is, (addr & 0x1f), size);
break;
case 0xc00 ... 0xc3f: /* PCI interrupt control */
if (addr & 4) {
val = 0;
}
break;
- case 0x1000 ... 0x1080: /* OBIO interrupt control */
+ case 0x1000 ... 0x107f: /* OBIO interrupt control */
if (addr & 4) {
val = s->obio_irq_map[(addr & 0xff) >> 3];
} else {
val = 0;
}
break;
+ case 0x1080 ... 0x108f: /* PCI bus error */
+ if (addr & 4) {
+ val = s->pci_err_irq_map[(addr & 0xf) >> 3];
+ } else {
+ val = 0;
+ }
+ break;
case 0x2000 ... 0x202f: /* PCI control */
val = s->pci_control[(addr & 0x3f) >> 2];
break;
for (i = 0; i < 8; i++) {
s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
}
+ for (i = 0; i < 2; i++) {
+ s->pci_err_irq_map[i] = (0x1f << 6) | 0x30;
+ }
for (i = 0; i < 32; i++) {
s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
}