Hi Linu, On 08/09/2017 12:52, Linu Cherian wrote: > Hi Eric, > > On Fri Sep 01, 2017 at 07:21:08PM +0200, Eric Auger wrote: >> From: Prem Mallappa <prem.malla...@broadcom.com> >> >> This patch implements a skeleton for the smmuv3 device. >> Datatypes and register definitions are introduced. The MMIO >> region, the interrupts and the queue are initialized (PRI is >> not supported). >> >> Only the MMIO read operation is implemented here. >> >> Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com> >> Signed-off-by: Eric Auger <eric.au...@redhat.com> >> >> --- >> v6 -> v7: >> - split into several patches >> >> v5 -> v6: >> - Use IOMMUMemoryregion >> - regs become uint32_t and fix 64b MMIO access (.impl) >> - trace_smmuv3_write/read_mmio take the size param >> >> v4 -> v5: >> - change smmuv3_translate proto (IOMMUAccessFlags flag) >> - has_stagex replaced by is_ste_stagex >> - smmu_cfg_populate removed >> - added smmuv3_decode_config and reworked error management >> - remwork the naming of IOMMU mrs >> - fix SMMU_CMDQ_CONS offset >> >> v3 -> v4 >> - smmu_irq_update >> - fix hash key allocation >> - set smmu_iommu_ops >> - set SMMU_REG_CR0, >> - smmuv3_translate: ret.perm not set in bypass mode >> - use trace events >> - renamed STM2U64 into L1STD_L2PTR and STMSPAN into L1STD_SPAN >> - rework smmu_find_ste >> - fix tg2granule in TT0/0b10 corresponds to 16kB >> >> v2 -> v3: >> - move creation of include/hw/arm/smmuv3.h to this patch to fix compil issue >> - compilation allowed >> - fix sbus allocation in smmu_init_pci_iommu >> - restructure code into headers >> - misc cleanups >> --- >> hw/arm/Makefile.objs | 2 +- >> hw/arm/smmuv3-internal.h | 201 +++++++++++++++++++++++++++++++++++++++ >> hw/arm/smmuv3.c | 239 >> +++++++++++++++++++++++++++++++++++++++++++++++ >> hw/arm/trace-events | 3 + >> include/hw/arm/smmuv3.h | 79 ++++++++++++++++ >> 5 files changed, 523 insertions(+), 1 deletion(-) >> create mode 100644 hw/arm/smmuv3-internal.h >> create mode 100644 hw/arm/smmuv3.c >> create mode 100644 include/hw/arm/smmuv3.h >> >> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs >> index 5b2d38d..a7c808b 100644 >> --- a/hw/arm/Makefile.objs >> +++ b/hw/arm/Makefile.objs >> @@ -19,4 +19,4 @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o >> obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o >> obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o >> obj-$(CONFIG_MPS2) += mps2.o >> -obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o >> +obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o >> diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h >> new file mode 100644 >> index 0000000..488acc8 >> --- /dev/null >> +++ b/hw/arm/smmuv3-internal.h >> @@ -0,0 +1,201 @@ >> +/* >> + * ARM SMMUv3 support - Internal API >> + * >> + * Copyright (C) 2014-2016 Broadcom Corporation >> + * Copyright (c) 2017 Red Hat, Inc. >> + * Written by Prem Mallappa, Eric Auger >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License as published by >> + * the Free Software Foundation, either version 2 of the License, or >> + * (at your option) any later version. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + * >> + * You should have received a copy of the GNU General Public License along >> + * with this program; if not, see <http://www.gnu.org/licenses/>. >> + */ >> + >> +#ifndef HW_ARM_SMMU_V3_INTERNAL_H >> +#define HW_ARM_SMMU_V3_INTERNAL_H >> + >> +#include "trace.h" >> +#include "qemu/error-report.h" >> +#include "hw/arm/smmu-common.h" >> + >> +/***************************** >> + * MMIO Register >> + *****************************/ >> +enum { >> + SMMU_REG_IDR0 = 0x0, >> + >> +/* IDR0 Field Values and supported features */ >> + >> +#define SMMU_IDR0_S2P 1 /* stage 2 */ >> +#define SMMU_IDR0_S1P 1 /* stage 1 */ >> +#define SMMU_IDR0_TTF 2 /* Aarch64 only - not Aarch32 (LPAE) */ >> +#define SMMU_IDR0_COHACC 1 /* IO coherent access */ >> +#define SMMU_IDR0_HTTU 2 /* Access and Dirty flag update */ >> +#define SMMU_IDR0_HYP 0 /* Hypervisor Stage 1 contexts */ >> +#define SMMU_IDR0_ATS 0 /* PCIe RC ATS */ >> +#define SMMU_IDR0_ASID16 1 /* 16-bit ASID */ >> +#define SMMU_IDR0_PRI 0 /* Page Request Interface */ >> +#define SMMU_IDR0_VMID16 0 /* 16-bit VMID */ >> +#define SMMU_IDR0_CD2L 0 /* 2-level Context Descriptor table */ >> +#define SMMU_IDR0_STALL 1 /* Stalling fault model */ >> +#define SMMU_IDR0_TERM 1 /* Termination model behaviour */ >> +#define SMMU_IDR0_STLEVEL 1 /* Multi-level Stream Table */ >> + >> +#define SMMU_IDR0_S2P_SHIFT 0 >> +#define SMMU_IDR0_S1P_SHIFT 1 >> +#define SMMU_IDR0_TTF_SHIFT 2 >> +#define SMMU_IDR0_COHACC_SHIFT 4 >> +#define SMMU_IDR0_HTTU_SHIFT 6 >> +#define SMMU_IDR0_HYP_SHIFT 9 >> +#define SMMU_IDR0_ATS_SHIFT 10 >> +#define SMMU_IDR0_ASID16_SHIFT 12 >> +#define SMMU_IDR0_PRI_SHIFT 16 >> +#define SMMU_IDR0_VMID16_SHIFT 18 >> +#define SMMU_IDR0_CD2L_SHIFT 19 >> +#define SMMU_IDR0_STALL_SHIFT 24 >> +#define SMMU_IDR0_TERM_SHIFT 26 >> +#define SMMU_IDR0_STLEVEL_SHIFT 27 >> + >> + SMMU_REG_IDR1 = 0x4, >> +#define SMMU_IDR1_SIDSIZE 16 >> + SMMU_REG_IDR2 = 0x8, >> + SMMU_REG_IDR3 = 0xc, >> + SMMU_REG_IDR4 = 0x10, >> + SMMU_REG_IDR5 = 0x14, >> +#define SMMU_IDR5_GRAN_SHIFT 4 >> +#define SMMU_IDR5_GRAN 0b101 /* GRAN4K, GRAN64K */ >> +#define SMMU_IDR5_OAS 4 /* 44 bits */ >> + SMMU_REG_IIDR = 0x1c, >> + SMMU_REG_CR0 = 0x20, >> + >> +#define SMMU_CR0_SMMU_ENABLE (1 << 0) >> +#define SMMU_CR0_PRIQ_ENABLE (1 << 1) >> +#define SMMU_CR0_EVTQ_ENABLE (1 << 2) >> +#define SMMU_CR0_CMDQ_ENABLE (1 << 3) >> +#define SMMU_CR0_ATS_CHECK (1 << 4) >> + >> + SMMU_REG_CR0_ACK = 0x24, >> + SMMU_REG_CR1 = 0x28, >> + SMMU_REG_CR2 = 0x2c, >> + >> + SMMU_REG_STATUSR = 0x40, >> + >> + SMMU_REG_IRQ_CTRL = 0x50, >> + SMMU_REG_IRQ_CTRL_ACK = 0x54, >> + >> +#define SMMU_IRQ_CTRL_GERROR_EN (1 << 0) >> +#define SMMU_IRQ_CTRL_EVENT_EN (1 << 1) >> +#define SMMU_IRQ_CTRL_PRI_EN (1 << 2) >> + >> + SMMU_REG_GERROR = 0x60, >> + >> +#define SMMU_GERROR_CMDQ (1 << 0) >> +#define SMMU_GERROR_EVENTQ_ABT (1 << 2) >> +#define SMMU_GERROR_PRIQ_ABT (1 << 3) >> +#define SMMU_GERROR_MSI_CMDQ_ABT (1 << 4) >> +#define SMMU_GERROR_MSI_EVENTQ_ABT (1 << 5) >> +#define SMMU_GERROR_MSI_PRIQ_ABT (1 << 6) >> +#define SMMU_GERROR_MSI_GERROR_ABT (1 << 7) >> +#define SMMU_GERROR_SFM_ERR (1 << 8) >> + >> + SMMU_REG_GERRORN = 0x64, >> + SMMU_REG_GERROR_IRQ_CFG0 = 0x68, >> + SMMU_REG_GERROR_IRQ_CFG1 = 0x70, >> + SMMU_REG_GERROR_IRQ_CFG2 = 0x74, >> + >> + /* SMMU_BASE_RA Applies to STRTAB_BASE, CMDQ_BASE and EVTQ_BASE */ >> +#define SMMU_BASE_RA (1ULL << 62) >> + SMMU_REG_STRTAB_BASE = 0x80, >> + SMMU_REG_STRTAB_BASE_CFG = 0x88, >> + >> + SMMU_REG_CMDQ_BASE = 0x90, >> + SMMU_REG_CMDQ_PROD = 0x98, >> + SMMU_REG_CMDQ_CONS = 0x9c, >> + /* CMD Consumer (CONS) */ >> +#define SMMU_CMD_CONS_ERR_SHIFT 24 >> +#define SMMU_CMD_CONS_ERR_BITS 7 >> + >> + SMMU_REG_EVTQ_BASE = 0xa0, >> + SMMU_REG_EVTQ_PROD = 0xa8, >> + SMMU_REG_EVTQ_CONS = 0xac, >> + SMMU_REG_EVTQ_IRQ_CFG0 = 0xb0, >> + SMMU_REG_EVTQ_IRQ_CFG1 = 0xb8, >> + SMMU_REG_EVTQ_IRQ_CFG2 = 0xbc, >> + >> + SMMU_REG_PRIQ_BASE = 0xc0, >> + SMMU_REG_PRIQ_PROD = 0xc8, >> + SMMU_REG_PRIQ_CONS = 0xcc, >> + SMMU_REG_PRIQ_IRQ_CFG0 = 0xd0, >> + SMMU_REG_PRIQ_IRQ_CFG1 = 0xd8, >> + SMMU_REG_PRIQ_IRQ_CFG2 = 0xdc, >> + >> + SMMU_ID_REGS_OFFSET = 0xfd0, >> + >> + /* Secure registers are not used for now */ >> + SMMU_SECURE_OFFSET = 0x8000, >> +}; >> + >> +/********************** >> + * Data Structures >> + **********************/ >> + >> +struct __smmu_data2 { >> + uint32_t word[2]; >> +}; >> + >> +struct __smmu_data8 { >> + uint32_t word[8]; >> +}; >> + >> +struct __smmu_data16 { >> + uint32_t word[16]; >> +}; >> + >> +struct __smmu_data4 { >> + uint32_t word[4]; >> +}; >> + >> +typedef struct __smmu_data4 Cmd; /* Command Entry */ >> +typedef struct __smmu_data8 Evt; /* Event Entry */ >> + >> +/***************************** >> + * Register Access Primitives >> + *****************************/ >> + >> +static inline void smmu_write32_reg(SMMUV3State *s, uint32_t addr, uint32_t >> val) >> +{ >> + s->regs[addr >> 2] = val; >> +} >> + >> +static inline void smmu_write64_reg(SMMUV3State *s, uint32_t addr, uint64_t >> val) >> +{ >> + addr >>= 2; >> + s->regs[addr] = extract64(val, 0, 32); >> + s->regs[addr + 1] = extract64(val, 32, 32); >> +} >> + >> +static inline uint32_t smmu_read32_reg(SMMUV3State *s, uint32_t addr) >> +{ >> + return s->regs[addr >> 2]; >> +} >> + >> +static inline uint64_t smmu_read64_reg(SMMUV3State *s, uint32_t addr) >> +{ >> + addr >>= 2; >> + return s->regs[addr] | ((uint64_t)(s->regs[addr + 1]) << 32); >> +} >> + >> +static inline int smmu_enabled(SMMUV3State *s) >> +{ >> + return smmu_read32_reg(s, SMMU_REG_CR0) & SMMU_CR0_SMMU_ENABLE; >> +} >> + >> +#endif >> diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c >> new file mode 100644 >> index 0000000..0a7cd1c >> --- /dev/null >> +++ b/hw/arm/smmuv3.c >> @@ -0,0 +1,239 @@ >> +/* >> + * Copyright (C) 2014-2016 Broadcom Corporation >> + * Copyright (c) 2017 Red Hat, Inc. >> + * Written by Prem Mallappa, Eric Auger >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License as published by >> + * the Free Software Foundation, either version 2 of the License, or >> + * (at your option) any later version. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + * >> + * You should have received a copy of the GNU General Public License along >> + * with this program; if not, see <http://www.gnu.org/licenses/>. >> + */ >> + >> +#include "qemu/osdep.h" >> +#include "hw/boards.h" >> +#include "sysemu/sysemu.h" >> +#include "hw/sysbus.h" >> +#include "hw/pci/pci.h" >> +#include "exec/address-spaces.h" >> +#include "trace.h" >> +#include "qemu/error-report.h" >> + >> +#include "hw/arm/smmuv3.h" >> +#include "smmuv3-internal.h" >> + >> +static void smmuv3_init_regs(SMMUV3State *s) >> +{ >> + uint32_t data = >> + SMMU_IDR0_STLEVEL << SMMU_IDR0_STLEVEL_SHIFT | >> + SMMU_IDR0_TERM << SMMU_IDR0_TERM_SHIFT | >> + SMMU_IDR0_STALL << SMMU_IDR0_STALL_SHIFT | >> + SMMU_IDR0_VMID16 << SMMU_IDR0_VMID16_SHIFT | >> + SMMU_IDR0_PRI << SMMU_IDR0_PRI_SHIFT | >> + SMMU_IDR0_ASID16 << SMMU_IDR0_ASID16_SHIFT | >> + SMMU_IDR0_ATS << SMMU_IDR0_ATS_SHIFT | >> + SMMU_IDR0_HYP << SMMU_IDR0_HYP_SHIFT | >> + SMMU_IDR0_HTTU << SMMU_IDR0_HTTU_SHIFT | >> + SMMU_IDR0_COHACC << SMMU_IDR0_COHACC_SHIFT | >> + SMMU_IDR0_TTF << SMMU_IDR0_TTF_SHIFT | >> + SMMU_IDR0_S1P << SMMU_IDR0_S1P_SHIFT | >> + SMMU_IDR0_S2P << SMMU_IDR0_S2P_SHIFT; >> + >> + smmu_write32_reg(s, SMMU_REG_IDR0, data); >> + >> +#define SMMU_QUEUE_SIZE_LOG2 19 >> + data = >> + 1 << 27 | /* Attr Types override */ >> + SMMU_QUEUE_SIZE_LOG2 << 21 | /* Cmd Q size */ >> + SMMU_QUEUE_SIZE_LOG2 << 16 | /* Event Q size */ >> + SMMU_QUEUE_SIZE_LOG2 << 11 | /* PRI Q size */ >> + 0 << 6 | /* SSID not supported */ >> + SMMU_IDR1_SIDSIZE; >> + >> + smmu_write32_reg(s, SMMU_REG_IDR1, data); >> + >> + s->sid_size = SMMU_IDR1_SIDSIZE; >> + >> + data = SMMU_IDR5_GRAN << SMMU_IDR5_GRAN_SHIFT | SMMU_IDR5_OAS; > > For VFIO case, should we not set the granule size based on underlying > pagesize bitmap derived from VFIO_IOMMU_GET_INFO. Else if guest kernel > is build with 4k page size and the host kernel is 64k we would start > getting map errors.
yes at the moment this is not implemented (1st target of the series is virtio/vhost). On Intel if I understand correctly the minimum requested is 4K, 2MB. 1GB is optional. I understand the emulated model does not expose 1GB (FL1GP = 0). On ARM nothing is mandatory although 4K and 64K minimal granules are "strongly recommended", leading to the following additional sizes. if (reg & IDR5_GRAN64K) smmu->pgsize_bitmap |= SZ_64K | SZ_512M; if (reg & IDR5_GRAN16K) smmu->pgsize_bitmap |= SZ_16K | SZ_32M; if (reg & IDR5_GRAN4K) smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G; Maybe we can override the ID5 values using the vfio_memory_listener. I will try to prototype this idea. Thanks Eric > > > >> + >> + smmu_write32_reg(s, SMMU_REG_IDR5, data); >> +} >> + >> +static void smmuv3_init_queues(SMMUV3State *s) >> +{ >> + s->cmdq.prod = 0; >> + s->cmdq.cons = 0; >> + s->cmdq.wrap.prod = 0; >> + s->cmdq.wrap.cons = 0; >> + >> + s->evtq.prod = 0; >> + s->evtq.cons = 0; >> + s->evtq.wrap.prod = 0; >> + s->evtq.wrap.cons = 0; >> + >> + s->cmdq.entries = SMMU_QUEUE_SIZE_LOG2; >> + s->cmdq.ent_size = sizeof(Cmd); >> + s->evtq.entries = SMMU_QUEUE_SIZE_LOG2; >> + s->evtq.ent_size = sizeof(Evt); >> +} >> + >> +static void smmuv3_init(SMMUV3State *s) >> +{ >> + smmuv3_init_regs(s); >> + smmuv3_init_queues(s); >> +} >> + >> +static inline void smmu_update_base_reg(SMMUV3State *s, uint64_t *base, >> + uint64_t val) >> +{ >> + *base = val & ~(SMMU_BASE_RA | 0x3fULL); >> +} >> + >> +static void smmu_write_mmio_fixup(SMMUV3State *s, hwaddr *addr) >> +{ >> + switch (*addr) { >> + case 0x100a8: case 0x100ac: /* Aliasing => page0 registers */ >> + case 0x100c8: case 0x100cc: >> + *addr ^= (hwaddr)0x10000; >> + } >> +} >> + >> +static void smmu_write_mmio(void *opaque, hwaddr addr, >> + uint64_t val, unsigned size) >> +{ >> +} >> + >> +static uint64_t smmu_read_mmio(void *opaque, hwaddr addr, unsigned size) >> +{ >> + SMMUState *sys = opaque; >> + SMMUV3State *s = SMMU_V3_DEV(sys); >> + uint64_t val; >> + >> + smmu_write_mmio_fixup(s, &addr); >> + >> + /* Primecell/Corelink ID registers */ >> + switch (addr) { >> + case 0xFF0 ... 0xFFC: >> + case 0xFDC ... 0xFE4: >> + val = 0; >> + error_report("addr:0x%"PRIx64" val:0x%"PRIx64, addr, val); >> + break; >> + case SMMU_REG_STRTAB_BASE ... SMMU_REG_CMDQ_BASE: >> + case SMMU_REG_EVTQ_BASE: >> + case SMMU_REG_PRIQ_BASE ... SMMU_REG_PRIQ_IRQ_CFG1: >> + val = smmu_read64_reg(s, addr); >> + break; >> + default: >> + val = (uint64_t)smmu_read32_reg(s, addr); >> + break; >> + } >> + >> + trace_smmuv3_read_mmio(addr, val, size); >> + return val; >> +} >> + >> +static const MemoryRegionOps smmu_mem_ops = { >> + .read = smmu_read_mmio, >> + .write = smmu_write_mmio, >> + .endianness = DEVICE_LITTLE_ENDIAN, >> + .valid = { >> + .min_access_size = 4, >> + .max_access_size = 8, >> + }, >> + .impl = { >> + .min_access_size = 4, >> + .max_access_size = 8, >> + }, >> +}; >> + >> +static void smmu_init_irq(SMMUV3State *s, SysBusDevice *dev) >> +{ >> + int i; >> + >> + for (i = 0; i < ARRAY_SIZE(s->irq); i++) { >> + sysbus_init_irq(dev, &s->irq[i]); >> + } >> +} >> + >> +static void smmu_reset(DeviceState *dev) >> +{ >> + SMMUV3State *s = SMMU_V3_DEV(dev); >> + smmuv3_init(s); >> +} >> + >> +static void smmu_realize(DeviceState *d, Error **errp) >> +{ >> + SMMUState *sys = SMMU_SYS_DEV(d); >> + SMMUV3State *s = SMMU_V3_DEV(sys); >> + SysBusDevice *dev = SYS_BUS_DEVICE(d); >> + >> + memory_region_init_io(&sys->iomem, OBJECT(s), >> + &smmu_mem_ops, sys, TYPE_SMMU_V3_DEV, 0x20000); >> + >> + sys->mrtypename = g_strdup(TYPE_SMMUV3_IOMMU_MEMORY_REGION); >> + >> + sysbus_init_mmio(dev, &sys->iomem); >> + >> + smmu_init_irq(s, dev); >> +} >> + >> +static const VMStateDescription vmstate_smmuv3 = { >> + .name = "smmuv3", >> + .version_id = 1, >> + .minimum_version_id = 1, >> + .fields = (VMStateField[]) { >> + VMSTATE_UINT32_ARRAY(regs, SMMUV3State, SMMU_NREGS), >> + VMSTATE_END_OF_LIST(), >> + }, >> +}; >> + >> +static void smmuv3_instance_init(Object *obj) >> +{ >> + /* Nothing much to do here as of now */ >> +} >> + >> +static void smmuv3_class_init(ObjectClass *klass, void *data) >> +{ >> + DeviceClass *dc = DEVICE_CLASS(klass); >> + >> + dc->reset = smmu_reset; >> + dc->vmsd = &vmstate_smmuv3; >> + dc->realize = smmu_realize; >> +} >> + >> +static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass, >> + void *data) >> +{ >> +} >> + >> +static const TypeInfo smmuv3_type_info = { >> + .name = TYPE_SMMU_V3_DEV, >> + .parent = TYPE_SMMU_DEV_BASE, >> + .instance_size = sizeof(SMMUV3State), >> + .instance_init = smmuv3_instance_init, >> + .class_data = NULL, >> + .class_size = sizeof(SMMUV3Class), >> + .class_init = smmuv3_class_init, >> +}; >> + >> +static const TypeInfo smmuv3_iommu_memory_region_info = { >> + .parent = TYPE_IOMMU_MEMORY_REGION, >> + .name = TYPE_SMMUV3_IOMMU_MEMORY_REGION, >> + .class_init = smmuv3_iommu_memory_region_class_init, >> +}; >> + >> +static void smmuv3_register_types(void) >> +{ >> + type_register(&smmuv3_type_info); >> + type_register(&smmuv3_iommu_memory_region_info); >> +} >> + >> +type_init(smmuv3_register_types) >> + >> diff --git a/hw/arm/trace-events b/hw/arm/trace-events >> index c67cd39..8affbf7 100644 >> --- a/hw/arm/trace-events >> +++ b/hw/arm/trace-events >> @@ -14,3 +14,6 @@ smmu_page_walk_level_block_pte(int stage, int level, >> uint64_t baseaddr, uint64_t >> smmu_page_walk_level_table_pte(int stage, int level, uint64_t baseaddr, >> uint64_t pteaddr, uint64_t pte, uint64_t address) "stage=%d, level=%d >> base@=0x%"PRIx64" pte@=0x%"PRIx64" pte=0x%"PRIx64" next table address = >> 0x%"PRIx64 >> smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte) >> "baseaddr=0x%"PRIx64" index=0x%x, pteaddr=0x%"PRIx64", pte=0x%"PRIx64 >> smmu_set_translated_address(hwaddr iova, hwaddr pa) "iova = 0x%"PRIx64" -> >> pa = 0x%"PRIx64 >> + >> +#hw/arm/smmuv3.c >> +smmuv3_read_mmio(hwaddr addr, uint64_t val, unsigned size) "addr: >> 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x" >> diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h >> new file mode 100644 >> index 0000000..0c8973d >> --- /dev/null >> +++ b/include/hw/arm/smmuv3.h >> @@ -0,0 +1,79 @@ >> +/* >> + * Copyright (C) 2014-2016 Broadcom Corporation >> + * Copyright (c) 2017 Red Hat, Inc. >> + * Written by Prem Mallappa, Eric Auger >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License as published by >> + * the Free Software Foundation, either version 2 of the License, or >> + * (at your option) any later version. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + * >> + * You should have received a copy of the GNU General Public License along >> + * with this program; if not, see <http://www.gnu.org/licenses/>. >> + */ >> + >> +#ifndef HW_ARM_SMMUV3_H >> +#define HW_ARM_SMMUV3_H >> + >> +#include "hw/arm/smmu-common.h" >> + >> +#define TYPE_SMMUV3_IOMMU_MEMORY_REGION "smmuv3-iommu-memory-region" >> + >> +#define SMMU_NREGS 0x200 >> + >> +typedef struct SMMUQueue { >> + hwaddr base; >> + uint32_t prod; >> + uint32_t cons; >> + union { >> + struct { >> + uint8_t prod:1; >> + uint8_t cons:1; >> + }; >> + uint8_t unused; >> + } wrap; >> + >> + uint16_t entries; /* Number of entries */ >> + uint8_t ent_size; /* Size of entry in bytes */ >> + uint8_t shift; /* Size in log2 */ >> +} SMMUQueue; >> + >> +typedef struct SMMUV3State { >> + SMMUState smmu_state; >> + >> + /* Local cache of most-frequently used registers */ >> +#define SMMU_FEATURE_2LVL_STE (1 << 0) >> + uint32_t features; >> + uint16_t sid_size; >> + uint16_t sid_split; >> + uint64_t strtab_base; >> + >> + uint32_t regs[SMMU_NREGS]; >> + >> + qemu_irq irq[4]; >> + SMMUQueue cmdq, evtq; >> + >> +} SMMUV3State; >> + >> +typedef enum { >> + SMMU_IRQ_EVTQ, >> + SMMU_IRQ_PRIQ, >> + SMMU_IRQ_CMD_SYNC, >> + SMMU_IRQ_GERROR, >> +} SMMUIrq; >> + >> +typedef struct { >> + SMMUBaseClass smmu_base_class; >> +} SMMUV3Class; >> + >> +#define TYPE_SMMU_V3_DEV "smmuv3" >> +#define SMMU_V3_DEV(obj) OBJECT_CHECK(SMMUV3State, (obj), TYPE_SMMU_V3_DEV) >> +#define SMMU_V3_DEVICE_GET_CLASS(obj) \ >> + OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_SMMU_V3_DEV) >> + >> +#endif >> -- >> 2.5.5 >> >> >