qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [Qemu-arm] [PATCH v7 05/20] hw/arm/smmuv3: Skeleton


From: Linu Cherian
Subject: Re: [Qemu-devel] [Qemu-arm] [PATCH v7 05/20] hw/arm/smmuv3: Skeleton
Date: Tue, 12 Sep 2017 11:44:21 +0530
User-agent: Mutt/1.5.21 (2010-09-15)

On Fri Sep 08, 2017 at 05:18:19PM +0200, Auger Eric wrote:
> 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 <address@hidden>
> >>
> >> 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 <address@hidden>
> >> Signed-off-by: Eric Auger <address@hidden>
> >>
> >> ---
> >> 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.

Ok. Thanks.


> 
> 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 
> >> address@hidden"PRIx64" address@hidden"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
> >>
> >>
> > 

-- 
Linu cherian



reply via email to

[Prev in Thread] Current Thread [Next in Thread]