mirror of https://github.com/xqemu/xqemu.git
sun4m: implement IOMMU translation using IOMMU memory region
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
This commit is contained in:
parent
331b7fc156
commit
8413846631
|
@ -278,6 +278,49 @@ static void iommu_bad_addr(IOMMUState *s, hwaddr addr,
|
||||||
qemu_irq_raise(s->irq);
|
qemu_irq_raise(s->irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
void sparc_iommu_memory_rw(void *opaque, hwaddr addr,
|
void sparc_iommu_memory_rw(void *opaque, hwaddr addr,
|
||||||
uint8_t *buf, int len, int is_write)
|
uint8_t *buf, int len, int is_write)
|
||||||
{
|
{
|
||||||
|
@ -340,6 +383,11 @@ static void iommu_init(Object *obj)
|
||||||
IOMMUState *s = SUN4M_IOMMU(obj);
|
IOMMUState *s = SUN4M_IOMMU(obj);
|
||||||
SysBusDevice *dev = SYS_BUS_DEVICE(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);
|
sysbus_init_irq(dev, &s->irq);
|
||||||
|
|
||||||
memory_region_init_io(&s->iomem, obj, &iommu_mem_ops, s, "iommu",
|
memory_region_init_io(&s->iomem, obj, &iommu_mem_ops, s, "iommu",
|
||||||
|
@ -369,9 +417,23 @@ static const TypeInfo iommu_info = {
|
||||||
.class_init = iommu_class_init,
|
.class_init = iommu_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void sun4m_iommu_memory_region_class_init(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
|
||||||
|
|
||||||
|
imrc->translate = sun4m_translate_iommu;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo sun4m_iommu_memory_region_info = {
|
||||||
|
.parent = TYPE_IOMMU_MEMORY_REGION,
|
||||||
|
.name = TYPE_SUN4M_IOMMU_MEMORY_REGION,
|
||||||
|
.class_init = sun4m_iommu_memory_region_class_init,
|
||||||
|
};
|
||||||
|
|
||||||
static void iommu_register_types(void)
|
static void iommu_register_types(void)
|
||||||
{
|
{
|
||||||
type_register_static(&iommu_info);
|
type_register_static(&iommu_info);
|
||||||
|
type_register_static(&sun4m_iommu_memory_region_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_init(iommu_register_types)
|
type_init(iommu_register_types)
|
||||||
|
|
|
@ -12,11 +12,16 @@
|
||||||
#define TYPE_SUN4M_IOMMU "iommu"
|
#define TYPE_SUN4M_IOMMU "iommu"
|
||||||
#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU)
|
#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU)
|
||||||
|
|
||||||
|
#define TYPE_SUN4M_IOMMU_MEMORY_REGION "sun4m-iommu-memory-region"
|
||||||
|
|
||||||
#define IOMMU_NREGS (4 * 4096 / 4)
|
#define IOMMU_NREGS (4 * 4096 / 4)
|
||||||
|
|
||||||
typedef struct IOMMUState {
|
typedef struct IOMMUState {
|
||||||
SysBusDevice parent_obj;
|
SysBusDevice parent_obj;
|
||||||
|
|
||||||
|
AddressSpace iommu_as;
|
||||||
|
IOMMUMemoryRegion iommu;
|
||||||
|
|
||||||
MemoryRegion iomem;
|
MemoryRegion iomem;
|
||||||
uint32_t regs[IOMMU_NREGS];
|
uint32_t regs[IOMMU_NREGS];
|
||||||
hwaddr iostart;
|
hwaddr iostart;
|
||||||
|
|
Loading…
Reference in New Issue