Re: [Qemu-devel] [PATCH v2 3/9] hw: arm: SMMUv3 emulation model

2016-09-25 Thread Prem Mallappa
Hi Edger,

I'm going to look at the PCI parts and get back to you with
> comments on that.
>
> Please do, by the time, I'll address your and Eric's comments.


> I've put another round of comments inline:
>
> Thanks



> > +inline void
> > +smmu_write_sysmem(hwaddr addr, void *buf, int len, bool secure)
> > +{
> > +MemTxAttrs attrs = {.unspecified = 1, .secure = secure};
> > +
> > +switch (len) {
> > +case 4:
> > +stl_le_phys(_space_memory, addr, *(uint32_t *)buf);
> > +break;
> > +case 8:
> > +stq_le_phys(_space_memory, addr, *(uint64_t *)buf);
> > +break;
> > +default:
> > +address_space_rw(_space_memory, addr,
> > + attrs, buf, len, true);
> > +}
> > +}
>
> Thinking about this, I think you should just remove these functions and
> always call dma_memory_read/write directly.
>
> It would be nice if you could add a property/link so that machine code
> can specify the MemoryRegion/address space to be used. You'll need a
> link to allow setup of the MemoryRegion and also some code to create
> an address space from the selected MR.
>
> You can have a look at the following code to see how it's done:
> exec.c cpu_exec_init()see object_property_add_link
> cpus.c qemu_init_vcpu()   see address_space_init_shareable
>
>
Sure, will do.


> > +#define smmu_evt_irq_enabled(s)   \
> > +__smmu_irq_enabled(s, SMMU_IRQ_CTRL_EVENT_EN)
> > +#define smmu_gerror_irq_enabled(s)  \
> > +__smmu_irq_enabled(s, SMMU_IRQ_CTRL_GERROR_EN)
> > +#define smmu_pri_irq_enabled(s) \
> > +__smmu_irq_enabled(s, SMMU_IRQ_CTRL_PRI_EN)
>
> Please drop the __ prefix on functions. _ prefixed functions are reserved
> and
> we usually avoid them.
>
> I don't think smmu_evt_irq_enabled() is very useful,
> smmu_irq_enabled(s, SMMU_IRQ_CTRL_EVENT_EN) is readable enough.
>
>
Got it.


> > +
> > +/*
> > + * MMIO Register
> > + */
> > +enum {
> > +SMMU_REG_IDR0= 0x0,
>
> For all regs, I think you should prefix regs with R_.
> And also do / 4, e.g:
>
> R_SMMU_REG_IDR1= 0x4 / 4,
>
> That way you can do s->regs[R_SMMU_REG_IDR1] and remove smmu_read32_reg.
> If you use the REG32 and FIELD macros from the register API you'll
> also be able to use the FIELD_ family of macros (e.g ARRAY_FIELD_EX32)
> to extract fields from regs.
>
> Will change this


> > +struct SMMUQueue {
> > + hwaddr base;
> > + uint32_t prod;
> > + uint32_t cons;
> > + union {
> > +  struct {
> > +   uint8_t prod:1;
> > +   uint8_t cons:1;
>
> Hi, Peter generally doesn't like bitfields. I'd stay away form
> them unless you have a good case. Just change them too bool.
>
>
This a wrap field, and used as a circular buffer full/empty indicator.
changing it to bool would loose its meaning, I'll change if its too much
off the
coding standard.



>
> > +
> > +typedef struct __smmu_data2  STEDesc; /* STE Level 1 Descriptor */
> > +typedef struct __smmu_data16 Ste; /* Stream Table Entry(STE) */
> > +typedef struct __smmu_data2  CDDesc;  /* CD Level 1 Descriptor */
> > +typedef struct __smmu_data16 Cd;  /* Context Descriptor(CD) */
> > +
> > +typedef struct __smmu_data4  Cmd; /* Command Entry */
> > +typedef struct __smmu_data8  Evt; /* Event Entry */
> > +typedef struct __smmu_data4  Pri; /* PRI entry */
>
>
> For all of these, I think it would be more useful if you would declare
> structs with actual fields representing the data structures.
> You can then declare load functions that load the STE from memory and
> decode the fields.
>
> E.g:
>
> typedef struct SMMUv3_STEDesc {
> bool valid;
>  etc...
> } SMMUv3_STEDesc;
>
> void smmuv3_load_ste(AddressSpace *as, dma_addr_t addr, SMMUv3_STEDesc
> *ste)
> {
> uint32_t buf[16];
> dma_memory_read(as, addr, buf, sizeof(*buf));
>
> ste->valid = extract32(buf[0], 0, 1);
> }
>
>
> Then, instead of for example doing STE_VALID(x), you can do ste->valid.
>
>
Thanks
I'll change it to appropriate names and delete where possible.


>
> > +#endif
> > diff --git a/hw/vfio/common.c b/hw/vfio/common.c
> > index e51ed3a..96da537 100644
> > --- a/hw/vfio/common.c
> > +++ b/hw/vfio/common.c
> > @@ -412,10 +412,10 @@ static void vfio_listener_region_add(MemoryListener
> *listener,
> >
> >  ret = vfio_dma_map(container, iova, int128_get64(llsize),
> > vaddr, section->readonly);
> > -if (ret) {
> >  error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "
> >   "0x%"HWADDR_PRIx", %p) = %d (%m)",
> >   container, iova, int128_get64(llsize), vaddr, ret);
> > +if (ret) {
> >  goto fail;
> >  }
>
>
> Shouldn't this be in a separate patch?
>
>
>
Will do this, thanks for your time


-- 
Cheers,
/Prem


Re: [Qemu-devel] [PATCH v2 9/9] [optional] arm: smmu-v3: ACPI IORT initial support

2016-09-23 Thread Prem Mallappa
On Fri, Sep 23, 2016 at 6:40 PM, Auger Eric <eric.au...@redhat.com> wrote:

> Hi Prem,
>
> On 12/09/2016 22:42, Prem Mallappa wrote:
> > On Fri, Sep 9, 2016 at 8:54 PM, Auger Eric <eric.au...@redhat.com>
> wrote:
> >
> >> Hi Prem,
> >>
> >> On 22/08/2016 18:17, Prem Mallappa wrote:
> >>> Added ACPI IORT tables, was needed for internal project purpose, but
> >>> posting here for anyone looking for testing ACPI on ARM platforms.
> >>> (P.S: Linux side IORT patches are WIP)
> >> I am also interested in IORT ITS group and currently prototyping
> >> something, hence my few comments/questions.
> >>>
> >>> Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
> >>> ---
> >>>  hw/arm/virt-acpi-build.c| 43 +++
> >>>  include/hw/acpi/acpi-defs.h | 84 ++
> >> +++
> >>>  2 files changed, 127 insertions(+)
> >>>
> >>> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> >>> index 1fa0581..d5fb69e 100644
> >>> --- a/hw/arm/virt-acpi-build.c
> >>> +++ b/hw/arm/virt-acpi-build.c
> >>> @@ -382,6 +382,45 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker,
> >> unsigned rsdt_tbl_offset)
> >>>  return rsdp_table;
> >>>  }
> >>>
> >>> +/*
> >>> + * TODO: Simple IORT for now, will add ID mappings as we go
> >>> + * basic idea is to instantiate SMMU from ACPI
> >>> + */
> >>> +static void
> >>> +build_iort(GArray *table_data, BIOSLinker *linker, VirtGuestInfo
> >> *guest_info)
> >>> +{
> >>> +int iort_start = table_data->len;
> >>> +AcpiIortTable *iort;
> >>> +AcpiIortNode *iort_node;
> >>> +AcpiIortSmmu3 *smmu;
> >>> +AcpiIortRC *rc;
> >>> +const MemMapEntry *memmap = guest_info->memmap;
> >>> +
> >>> +iort = acpi_data_push(table_data, sizeof(*iort));
> >>> +
> >>> +iort->length = sizeof(*iort);
> >> Isn't is supposed to be the length of the whole IORT (including the node
> >> cumulated sizes?)
> >>> +iort->node_offset = table_data->len - iort_start;
> >>> +iort->num_nodes++;
> >>> +
> >>> +smmu = acpi_data_push(table_data, sizeof(*smmu));
> >>> +iort_node = >iort_node;
> >>> +iort_node->type = 0x04;  /* SMMUv3 */
> >> To match existing code (include/hw/acpi/acpi-defs.h), maybe enum values
> >> can be created (ACPI_IORT_NODE_SMMU_V3). This also matches kernel enum.
> >>
> >> I have made these changes, will send out ASAP.
> >
> >
> >> More generally Shannon advised to use the same field names as the ones
> >> used in the kernel header: acpi_iort_node_type in include/acpi/actbl2.h
> >>
> >
> > Will change this accordingly
> >
> >
> >>> +iort_node->length = sizeof(*smmu);
> >>> +smmu->base_addr = cpu_to_le64(memmap[VIRT_SMMU].base);
> >>> +
> >>> +iort->num_nodes++;
> >>> +
> >>> +rc = acpi_data_push(table_data, sizeof(*rc));
> >>> +iort_node = >iort_node;
> >>> +iort_node->type = 0x02;  /* RC */
> >>> +iort_node->length = sizeof(*rc);
> >> I think the mem_access_prop field should be set to 1 now the host
> >> controller is assumed to be cache coherent.
> >>> +rc->ats_attr = 1;
> >> no ATS support instead?
> >>> +rc->pci_seg_num = 0;
> >> ID mappings are mandated for me to support MSIs with ITS.
> >>
> >
> > These changes are made as I write,
> >
> >
> >> Shannon told me we should match the kernel datatypes & fields
> >>
> >> for instance in include/acpi/actbl2.h we have:
> >>
> >> struct acpi_iort_id_mapping {
> >> u32 input_base; /* Lowest value in input range */
> >> u32 id_count;   /* Number of IDs */
> >> u32 output_base;/* Lowest value in output range */
> >> u32 output_reference;   /* A reference to the output node */
> >> u32 flags;
> >> };
> >>
> >> This also holds for other struct definitions.
> >>
> >>
> > Sure will change this accordingly.
>
> I currently have a series creating the IORT with an RC node and an ITS
> node. It is needed to complete the integration of the virtual ITS (to
> connect it with the PCI host controller). This originates from this
> patch: I added the RC->ITS ID mapping + the ITS node and tested it.
>
> I don't know how to proceed to get the 2 features (vSMMU and vITS)
> progress separately. Do you plan to respin this patch quickly?
> Otherwise, if you are busy with other things I propose you to respin
> fixing the few things above, splitting it into 3 patches, header [1],
> ITS node creation [2], RC node creation with RC->ITS mapping [3] while
> keeping credit to you on [1] and [3].
>
> Then we can have a 4th patch adding RC-> SMMU ID > ITS mapping?
>
> Please let me know what are your plans and what do you think.
>
> Thanks
>
> Eric
> >
> >
>

Hi Eric,
I have been busy with something else, however I have a wokring patch set
(unclean version)
which creates the IORT tables, with SMMU->RC->ITS with ITS id mapping
(routing all interrupts to single ITS).
I'll push them by to unstable branch by this Sunday.

-- 
Cheers,
/Prem


Re: [Qemu-devel] [PATCH v2 9/9] [optional] arm: smmu-v3: ACPI IORT initial support

2016-09-12 Thread Prem Mallappa
On Fri, Sep 9, 2016 at 8:54 PM, Auger Eric <eric.au...@redhat.com> wrote:

> Hi Prem,
>
> On 22/08/2016 18:17, Prem Mallappa wrote:
> > Added ACPI IORT tables, was needed for internal project purpose, but
> > posting here for anyone looking for testing ACPI on ARM platforms.
> > (P.S: Linux side IORT patches are WIP)
> I am also interested in IORT ITS group and currently prototyping
> something, hence my few comments/questions.
> >
> > Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
> > ---
> >  hw/arm/virt-acpi-build.c| 43 +++
> >  include/hw/acpi/acpi-defs.h | 84 ++
> +++
> >  2 files changed, 127 insertions(+)
> >
> > diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> > index 1fa0581..d5fb69e 100644
> > --- a/hw/arm/virt-acpi-build.c
> > +++ b/hw/arm/virt-acpi-build.c
> > @@ -382,6 +382,45 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker,
> unsigned rsdt_tbl_offset)
> >  return rsdp_table;
> >  }
> >
> > +/*
> > + * TODO: Simple IORT for now, will add ID mappings as we go
> > + * basic idea is to instantiate SMMU from ACPI
> > + */
> > +static void
> > +build_iort(GArray *table_data, BIOSLinker *linker, VirtGuestInfo
> *guest_info)
> > +{
> > +int iort_start = table_data->len;
> > +AcpiIortTable *iort;
> > +AcpiIortNode *iort_node;
> > +AcpiIortSmmu3 *smmu;
> > +AcpiIortRC *rc;
> > +const MemMapEntry *memmap = guest_info->memmap;
> > +
> > +iort = acpi_data_push(table_data, sizeof(*iort));
> > +
> > +iort->length = sizeof(*iort);
> Isn't is supposed to be the length of the whole IORT (including the node
> cumulated sizes?)
> > +iort->node_offset = table_data->len - iort_start;
> > +iort->num_nodes++;
> > +
> > +smmu = acpi_data_push(table_data, sizeof(*smmu));
> > +iort_node = >iort_node;
> > +iort_node->type = 0x04;  /* SMMUv3 */
> To match existing code (include/hw/acpi/acpi-defs.h), maybe enum values
> can be created (ACPI_IORT_NODE_SMMU_V3). This also matches kernel enum.
>
> I have made these changes, will send out ASAP.


> More generally Shannon advised to use the same field names as the ones
> used in the kernel header: acpi_iort_node_type in include/acpi/actbl2.h
>

Will change this accordingly


> > +iort_node->length = sizeof(*smmu);
> > +smmu->base_addr = cpu_to_le64(memmap[VIRT_SMMU].base);
> > +
> > +iort->num_nodes++;
> > +
> > +rc = acpi_data_push(table_data, sizeof(*rc));
> > +iort_node = >iort_node;
> > +iort_node->type = 0x02;  /* RC */
> > +iort_node->length = sizeof(*rc);
> I think the mem_access_prop field should be set to 1 now the host
> controller is assumed to be cache coherent.
> > +rc->ats_attr = 1;
> no ATS support instead?
> > +rc->pci_seg_num = 0;
> ID mappings are mandated for me to support MSIs with ITS.
>

These changes are made as I write,


> Shannon told me we should match the kernel datatypes & fields
>
> for instance in include/acpi/actbl2.h we have:
>
> struct acpi_iort_id_mapping {
> u32 input_base; /* Lowest value in input range */
> u32 id_count;   /* Number of IDs */
> u32 output_base;/* Lowest value in output range */
> u32 output_reference;   /* A reference to the output node */
> u32 flags;
> };
>
> This also holds for other struct definitions.
>
>
Sure will change this accordingly.


-- 
Cheers,
/Prem


Re: [Qemu-devel] [PATCH v2 1/9] log: Add new IOMMU type

2016-09-12 Thread Prem Mallappa
On Fri, Sep 9, 2016 at 9:06 PM, Auger Eric <eric.au...@redhat.com> wrote:

> Hi Prem,
>
> Missing commit message
>
> > Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
> > ---
> >  include/qemu/log.h | 1 +
> >  util/log.c | 2 ++
> >  2 files changed, 3 insertions(+)
> >
> > diff --git a/include/qemu/log.h b/include/qemu/log.h
> > index 234fa81..3dd2131 100644
> > --- a/include/qemu/log.h
> > +++ b/include/qemu/log.h
> > @@ -42,6 +42,7 @@ static inline bool qemu_log_separate(void)
> >  #define CPU_LOG_TB_NOCHAIN (1 << 13)
> >  #define CPU_LOG_PAGE   (1 << 14)
> >  #define LOG_TRACE  (1 << 15)
> > +#define CPU_LOG_IOMMU  (1 << 16)
> why is it prefixed with CPU_ ?
> besides all arm gic devices seem to use LOG_GUEST_ERROR. what is the
> rationale behind introducing a new enum?
>

Will change this to LOG_GUEST_ERROR, if others on the list are okay.


-- 
Cheers,
/Prem


Re: [Qemu-devel] [PATCH v2 2/9] devicetree: Added new APIs to make use of more fdt functions

2016-09-12 Thread Prem Mallappa
On Fri, Sep 9, 2016 at 9:32 PM, Auger Eric <eric.au...@redhat.com> wrote:

> Hi Prem,
>
> > SMMUv3 needs device tree entry like below
> To me the commit message should be more explicit and mention appendprop
> functionality
> >
> >  interrupt-names = "gerror", "priq", "eventq", "cmdq-sync";
> >
> > This patch introduces helper function to add entries like above
> >
> > Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
> > ---
> >  device_tree.c| 35 +++
> >  include/sysemu/device_tree.h | 18 ++
> >  2 files changed, 53 insertions(+)
> >
> > diff --git a/device_tree.c b/device_tree.c
> > index 6e06320..5d5966e 100644
> > --- a/device_tree.c
> > +++ b/device_tree.c
> > @@ -297,6 +297,24 @@ int qemu_fdt_setprop(void *fdt, const char
> *node_path,
> >  return r;
> >  }
> >
> > +int qemu_fdt_appendprop(void *fdt, const char *node_path,
> > + const char *property, const void *val, int size)
> > +{
> > +int r;
> > +
> > +r = fdt_appendprop(fdt, findnode_nofail(fdt, node_path), property,
> > +   val, size);
> > +if (r < 0) {
> > +error_report("%s: Couldn't set %s/%s: %s", __func__, node_path,
> > + property, fdt_strerror(r));
> > +exit(1);
> > +}
> > +
> > +return r;
> > +}
> > +
> > +
> spare void lines
> > +
> >  int qemu_fdt_setprop_cell(void *fdt, const char *node_path,
> >const char *property, uint32_t val)
> >  {
> > @@ -319,6 +337,23 @@ int qemu_fdt_setprop_u64(void *fdt, const char
> *node_path,
> >  return qemu_fdt_setprop(fdt, node_path, property, ,
> sizeof(val));
> >  }
> >
> > +int qemu_fdt_appendprop_string(void *fdt, const char *node_path,
> > +const char *property, const char *string)
> > +{
> > +int r;
> > +
> > +r = fdt_appendprop_string(fdt, findnode_nofail(fdt, node_path),
> > +  property, string);
> > +if (r < 0) {
> > +error_report("%s: Couldn't set %s/%s = %s: %s", __func__,
> > + node_path, property, string, fdt_strerror(r));
> > +exit(1);
> > +}
> > +
> > +return r;
> > +}
> > +
> same
> > +
> >  int qemu_fdt_setprop_string(void *fdt, const char *node_path,
> >  const char *property, const char *string)
> >  {
> > diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h
> > index 705650a..5a0a297 100644
> > --- a/include/sysemu/device_tree.h
> > +++ b/include/sysemu/device_tree.h
> > @@ -45,12 +45,16 @@ char **qemu_fdt_node_path(void *fdt, const char
> *name, char *compat,
> >
> >  int qemu_fdt_setprop(void *fdt, const char *node_path,
> >   const char *property, const void *val, int size);
> > +int qemu_fdt_appendprop(void *fdt, const char *node_path,
> > + const char *property, const void *val, int size);
> >  int qemu_fdt_setprop_cell(void *fdt, const char *node_path,
> >const char *property, uint32_t val);
> >  int qemu_fdt_setprop_u64(void *fdt, const char *node_path,
> >   const char *property, uint64_t val);
> >  int qemu_fdt_setprop_string(void *fdt, const char *node_path,
> >  const char *property, const char *string);
> > +int qemu_fdt_appendprop_string(void *fdt, const char *node_path,
> > +   const char *property, const char
> *string);
> >  int qemu_fdt_setprop_phandle(void *fdt, const char *node_path,
> >   const char *property,
> >   const char *target_node_path);
> > @@ -98,6 +102,20 @@ int qemu_fdt_add_subnode(void *fdt, const char
> *name);
> >   sizeof(qdt_tmp));
>   \
> >  } while (0)
> >
> > +
> same
> > +#define qemu_fdt_appendprop_cells(fdt, node_path, property, ...)
>   \
> > +do {
>   \
> > +uint32_t qdt_tmp[] = { __VA_ARGS__ };
>\
> > +int i;
>   \
> > +
>   \
> > +for (i = 0; i < ARRAY_SIZE(qdt_tmp); i++) {
>\
> > +qdt_tmp[i] = cpu_to_be32(qdt_tmp[i]);
>\
> > +}
>\
> > +qemu_fdt_appendprop(fdt, node_path, property, qdt_tmp,
>   \
> > + sizeof(qdt_tmp));
>   \
> > +} while (0)
> > +
> > +
> same here.
>
> Will take care of the extra blank lines.


> While I understand the benefits I think we could manage without this new
> API by using qemu_fdt_setprop and populating the uint32_t array separately.
>
> I'll give this a try and see how it goes.


> I understood the QEMU API for manipulating flattened trees was not
> supposed to grow too much but I don't have a strong option here. You
> should CC David Gibson I think.
>
>
Will sure do in the next drop.



-- 
Cheers,
/Prem


Re: [Qemu-devel] [PATCH v2 5/9] hw: arm: Add SMMUv3 to virt platform, create DTS accordingly

2016-09-12 Thread Prem Mallappa
On Fri, Sep 9, 2016 at 10:01 PM, Auger Eric <eric.au...@redhat.com> wrote:

> Hi Prem,
>
> > Default virt platform now creates SMMU device.
> > Default config to build SMMU device along is in previous patches.
> >
> > Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
> > ---
> >  hw/arm/virt.c | 62 ++
> +
> >  include/hw/arm/smmu.h | 33 +++
> >  include/hw/arm/virt.h |  2 ++
> >  3 files changed, 97 insertions(+)
> >  create mode 100644 include/hw/arm/smmu.h
> >
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> > index c5c125e..f3c7891 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -57,6 +57,7 @@
> >  #include "hw/smbios/smbios.h"
> >  #include "qapi/visitor.h"
> >  #include "standard-headers/linux/input.h"
> > +#include "hw/arm/smmu.h"
> >
> >  /* Number of external interrupt lines to configure the GIC with */
> >  #define NUM_IRQS 256
> > @@ -77,6 +78,7 @@ typedef struct VirtBoardInfo {
> >  uint32_t gic_phandle;
> >  uint32_t v2m_phandle;
> >  bool using_psci;
> > +uint32_t smmu_phandle;
> nit: would group the phandles together
> >  } VirtBoardInfo;
> >
> >  typedef struct {
> > @@ -175,6 +177,7 @@ static const MemMapEntry a15memmap[] = {
> >  [VIRT_FW_CFG] = { 0x0902, 0x0018 },
> >  [VIRT_GPIO] =   { 0x0903, 0x1000 },
> >  [VIRT_SECURE_UART] ={ 0x0904, 0x1000 },
> > +[VIRT_SMMU] =   { 0x0905, 0x0002 }, /* 128K,
> needed */
> >  [VIRT_MMIO] =   { 0x0a00, 0x0200 },
> >  /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that
> size */
> >  [VIRT_PLATFORM_BUS] =   { 0x0c00, 0x0200 },
> > @@ -195,9 +198,19 @@ static const int a15irqmap[] = {
> >  [VIRT_SECURE_UART] = 8,
> >  [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
> >  [VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */
> Currently don' we have NUM_GICV2M_SPIS = 64?
> > +[VIRT_SMMU] = 74,/* ...to 74 + NUM_SMMU_IRQS - 1 */
> >  [VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1
> */
> >  };
> >
> > +static const struct smmuirq {
> > +const char *name;
> > +} smmuirqmap[NUM_SMMU_IRQS] = {
> > +[SMMU_IRQ_EVTQ] = {"eventq"},
> > +[SMMU_IRQ_PRIQ] = {"priq"},
> > +[SMMU_IRQ_CMD_SYNC] = {"cmdq-sync"},
> > +[SMMU_IRQ_GERROR] = {"gerror"},
> > +};
> > +
> >  static VirtBoardInfo machines[] = {
> >  {
> >  .cpu_model = "cortex-a15",
> > @@ -938,6 +951,50 @@ static void create_pcie_irq_map(const VirtBoardInfo
> *vbi, uint32_t gic_phandle,
> > 0x7   /* PCI irq */);
> >  }
> >
> > +static void alloc_smmu_phandle(VirtBoardInfo *vbi)
> > +{
> I would rather put that code in create_smmu as it is done in create_gic
> for instance
> > +if (!vbi->smmu_phandle)
> > +vbi->smmu_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
> > +}
> > +
> > +static void create_smmu(VirtBoardInfo *vbi, qemu_irq *pic)
> > +{
> > +int i;
> > +char *smmu;
> > +const char compat[] = "arm,smmu-v3";
> > +int irq =  vbi->irqmap[VIRT_SMMU];
> > +hwaddr base = vbi->memmap[VIRT_SMMU].base;
> > +hwaddr size = vbi->memmap[VIRT_SMMU].size;
> > +int type = GIC_FDT_IRQ_TYPE_SPI;
> > +
> > +sysbus_create_varargs("smmuv3", base,
> > +  pic[irq],
> > +  pic[irq + 1],
> > +  pic[irq + 2],
> > +  pic[irq + 3],
> > +  NULL);
> > +
> > +smmu = g_strdup_printf("/smmuv3@%" PRIx64, base);
> > +qemu_fdt_add_subnode(vbi->fdt, smmu);
> > +qemu_fdt_setprop(vbi->fdt, smmu, "compatible", compat,
> sizeof(compat));
> > +qemu_fdt_setprop_sized_cells(vbi->fdt, smmu, "reg", 2, base, 2,
> size);
> > +
> > +for (i = 0; i < NUM_SMMU_IRQS; i++) {
> > +qemu_fdt_appendprop_cells(vbi->fdt, smmu, "interrupts",
> > +  type, irq + i,
> > +  GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> > +qemu_fdt_app

Re: [Qemu-devel] [PATCH v2 0/9] SMMUv3 Emulation support

2016-08-31 Thread Prem Mallappa
Oops, my mistake, copy-paste from different part.
I'll correct it in next spin.

Eric, you are most welcome to review though :)



On Thu, Sep 1, 2016 at 3:14 AM, Auger Eric <eric.au...@redhat.com> wrote:

> Hi Prem,
> On 22/08/2016 18:17, Prem Mallappa wrote:
> > v1 -> v2:
> >   - Adopted review comments from Eric Auger
> Although I am really interested in your series, those comments are not
> mine and credit should be given to somebody else (Edgar?)
>
> I will do my utmost to review it too ;-)
>
> Thanks
>
> Eric
> >   - Make SMMU_DPRINTF to internally call qemu_log
> >   (since translation requests are too many, we need
> control
> >on the type of log we want)
> >   - SMMUTransCfg modified to suite simplicity
> >   - Change RegInfo to uint64 register array
> >   - Code cleanup
> >   - Test cleanups
> >   - Reshuffled patches
> >
> > RFC -> v1:
> >   - As per SMMUv3 spec 16.0 (only is_ste_consistant() is noticeable)
> >   - Reworked register access/update logic
> >   - Factored out translation code for
> >   - single point bug fix
> >   - sharing/removal in future
> >   - (optional) Unit tests added, with PCI test device
> >   - S1 with 4k/64k, S1+S2 with 4k/64k
> >   - (S1 or S2) only can be verified by Linux 4.7 driver
> >   - (optional) Priliminary ACPI support
> >
> > RFC:
> >   - Implements SMMUv3 spec 11.0
> >   - Supported for PCIe devices,
> >   - Command Queue and Event Queue supported
> >   - LPAE only, S1 is supported and Tested, S2 not tested
> >   - BE mode Translation not supported
> >   - IRQ support (legacy, no MSI)
> >   - Tested with DPDK and e1000
> >
> > Patch 1: Add new log type for IOMMU transactions
> >
> > Patch 2: Adds support in virt.c to create both SMMUv3 device and dts
> entries
> >
> > Patch 2: Adds SMMUv3 model to QEMU
> >   Multiple files, big ones, translate functionality is split across
> to
> >   accomodate SMMUv2 model, and to remove when common translation
> feature
> >   (if) becomes available.
> >
> > Patch 3: Adds SMMU build support
> >
> > Patch 4: Some devicetree function to add support for SMMU's multiple
> interrupt
> >assignment with names
> >
> > << optional patches >>
> > Optional patches are posted for completeness or for those who wants to
> test.
> >
> > Patch 5: A simple PCI device which does DMA from 'src' to 'dst' given
> >src_addr, dst_addr and size, and is used by unit test, uses
> >pci_dma_read and pci_dma_write in a crude way but serves the
> purpose.
> >
> > Patch 6: Current libqos PCI helpers are x86 only, this addes a generic
> interface
> >
> > Patch 7: Unit tests for SMMU,
> >   - initializes SMMU device
> >   - initializes Test device
> >   - allocates page tables 1:1 mapping va == pa
> >   - allocates STE/CD accordingly for S1, S2, S1+S2
> >   - initiates DMA via PCI test device
> >   - verifies transfered data
> >
> > Patch 8: Added ACPI IORT tables, was needed for internal project
> purpose, but
> >posting here for anyone looking for testing ACPI on ARM platforms.
> >(P.S: Linux side IORT patches are WIP)
> >
> > Repo:
> > https://github.com/pmallappa/qemu/tree/upstream/smmuv3/v2
> >
> > To Test:
> > $ make tests/smmuv3-test
> > $ QTEST_QEMU_BINARY=aarch64-softmmu/qemu-system-aarch64
> tests/smmuv3-test
> > << expect lot of prints >>
> >
> > Any comments welcome..
> >
> > Cheers
> > /Prem
> >
> > Prem Mallappa (9):
> >   log: Add new IOMMU type
> >   devicetree: Added new APIs to make use of more fdt functions
> >   hw: arm: SMMUv3 emulation model
> >   hw: arm: Added SMMUv3 files for build
> >   hw: arm: Add SMMUv3 to virt platform, create DTS accordingly
> >   [optional] hw: misc: added testdev for smmu
> >   [optional] tests: libqos: generic pci probing helpers
> >   [optional] tests: SMMUv3 unit tests
> >   [optional] arm: smmu-v3: ACPI IORT initial support
> >
> >  default-configs/aarch64-softmmu.mak |1 +
> >  device_tree.c   |   35 +
> >  hw/arm/Makefile.objs|1 +
> >  hw/arm/smmu-common.c|  152 ++

[Qemu-devel] [PATCH v2 3/9] hw: arm: SMMUv3 emulation model

2016-08-22 Thread Prem Mallappa
Big patch adds SMMUv3 model to Qemu
  - As per SMMUv3 spec 16.0
  - Works with SMMUv3 driver in Linux 4.7rc1
  - Only LPAE mode translation supported
  - BE mode is not supported yet
  - Stage1, Stage2 and S1+S2
  - Suspend/resume not tested

Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 hw/arm/smmu-common.c |  152 +
 hw/arm/smmu-common.h |  141 +
 hw/arm/smmu-v3.c | 1369 ++
 hw/arm/smmuv3-internal.h |  432 +++
 hw/vfio/common.c |2 +-
 5 files changed, 2095 insertions(+), 1 deletion(-)
 create mode 100644 hw/arm/smmu-common.c
 create mode 100644 hw/arm/smmu-common.h
 create mode 100644 hw/arm/smmu-v3.c
 create mode 100644 hw/arm/smmuv3-internal.h

diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
new file mode 100644
index 000..bf2039b
--- /dev/null
+++ b/hw/arm/smmu-common.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2014-2016 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Prem Mallappa <pmall...@broadcom.com>
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "sysemu/sysemu.h"
+#include "exec/address-spaces.h"
+
+#include "smmu-common.h"
+
+inline MemTxResult smmu_read_sysmem(hwaddr addr, void *buf, int len,
+bool secure)
+{
+MemTxAttrs attrs = {.unspecified = 1, .secure = secure};
+
+switch (len) {
+case 4:
+*(uint32_t *)buf = ldl_le_phys(_space_memory, addr);
+break;
+case 8:
+*(uint64_t *)buf = ldq_le_phys(_space_memory, addr);
+break;
+default:
+return address_space_rw(_space_memory, addr,
+attrs, buf, len, false);
+}
+return MEMTX_OK;
+}
+
+inline void
+smmu_write_sysmem(hwaddr addr, void *buf, int len, bool secure)
+{
+MemTxAttrs attrs = {.unspecified = 1, .secure = secure};
+
+switch (len) {
+case 4:
+stl_le_phys(_space_memory, addr, *(uint32_t *)buf);
+break;
+case 8:
+stq_le_phys(_space_memory, addr, *(uint64_t *)buf);
+break;
+default:
+address_space_rw(_space_memory, addr,
+ attrs, buf, len, true);
+}
+}
+
+SMMUTransErr
+smmu_translate_64(SMMUTransCfg *cfg, uint32_t *pagesize,
+  uint32_t *perm, bool is_write)
+{
+int ret, level;
+int stage  = cfg->stage;
+int granule_sz = cfg->granule_sz[stage];
+int va_size= cfg->va_size[stage];
+hwaddr  va, addr, mask;
+hwaddr *outaddr;
+
+
+va = addr = cfg->va;/* or ipa in Stage2 */
+SMMU_DPRINTF(TT_1, "stage:%d\n", stage);
+assert(va_size == 64);  /* We dont support 32-bit yet */
+/* same location, for clearity */
+outaddr = >pa;
+
+level = 4 - (va_size - cfg->tsz[stage] - 4) / granule_sz;
+
+mask = (1ULL << (granule_sz + 3)) - 1;
+
+addr = extract64(cfg->ttbr[stage], 0, 48);
+addr &= ~((1ULL << (va_size - cfg->tsz[stage] -
+(granule_sz * (4 - level - 1);
+
+for (;;) {
+uint64_t desc;
+#ifdef ARM_SMMU_DEBUG
+uint64_t ored = (va >> (granule_sz * (4 - level))) & mask;
+SMMU_DPRINTF(TT_1,
+ "Level: %d va:%lx addr:%lx ored:%lx\n",
+ level, va, addr, ored);
+#endif
+addr |= (va >> (granule_sz * (4 - level))) & mask;
+addr &= ~7ULL;
+
+if (smmu_read_sysmem(addr, , sizeof(desc), false)) {
+ret = SMMU_TRANS_ERR_WALK_EXT_ABRT;
+SMMU_DPRINTF(CRIT, "Translation table read error lvl:%d\n", level);
+break;
+}
+
+SMMU_DPRINTF(TT_1,
+ "Level: %d gran_sz:%d mask:%lx addr:%lx desc:%lx\n",
+ level, granule_sz, mask, addr, desc);
+
+if (!(desc & 1) ||
+(!(desc & 2) && (level == 3))) {
+ret = SMMU_TRANS_ERR_TRANS;
+break;
+}
+
+/* We call again to resolve address at this 'level' */
+if (cfg->s2_needed) {
+uint32_t perm_s2, pagesize_s2;
+SMMUTransCfg s2cfg = *cfg;
+
+s2cfg.stage++;
+   

[Qemu-devel] [PATCH v2 9/9] [optional] arm: smmu-v3: ACPI IORT initial support

2016-08-22 Thread Prem Mallappa
Added ACPI IORT tables, was needed for internal project purpose, but
posting here for anyone looking for testing ACPI on ARM platforms.
(P.S: Linux side IORT patches are WIP)

Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 hw/arm/virt-acpi-build.c| 43 +++
 include/hw/acpi/acpi-defs.h | 84 +
 2 files changed, 127 insertions(+)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 1fa0581..d5fb69e 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -382,6 +382,45 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, 
unsigned rsdt_tbl_offset)
 return rsdp_table;
 }
 
+/*
+ * TODO: Simple IORT for now, will add ID mappings as we go
+ * basic idea is to instantiate SMMU from ACPI
+ */
+static void
+build_iort(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
+{
+int iort_start = table_data->len;
+AcpiIortTable *iort;
+AcpiIortNode *iort_node;
+AcpiIortSmmu3 *smmu;
+AcpiIortRC *rc;
+const MemMapEntry *memmap = guest_info->memmap;
+
+iort = acpi_data_push(table_data, sizeof(*iort));
+
+iort->length = sizeof(*iort);
+iort->node_offset = table_data->len - iort_start;
+iort->num_nodes++;
+
+smmu = acpi_data_push(table_data, sizeof(*smmu));
+iort_node = >iort_node;
+iort_node->type = 0x04;  /* SMMUv3 */
+iort_node->length = sizeof(*smmu);
+smmu->base_addr = cpu_to_le64(memmap[VIRT_SMMU].base);
+
+iort->num_nodes++;
+
+rc = acpi_data_push(table_data, sizeof(*rc));
+iort_node = >iort_node;
+iort_node->type = 0x02;  /* RC */
+iort_node->length = sizeof(*rc);
+rc->ats_attr = 1;
+rc->pci_seg_num = 0;
+
+build_header(linker, table_data, (void *)(table_data->data + iort_start),
+ "IORT", table_data->len - iort_start, 0, NULL, NULL);
+}
+
 static void
 build_spcr(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
 {
@@ -667,6 +706,7 @@ void virt_acpi_build(VirtGuestInfo *guest_info, 
AcpiBuildTables *tables)
  * MADT
  * MCFG
  * DSDT
+ * IORT = ACPI 6.0
  */
 
 /* DSDT is pointed to by FADT */
@@ -694,6 +734,9 @@ void virt_acpi_build(VirtGuestInfo *guest_info, 
AcpiBuildTables *tables)
 build_srat(tables_blob, tables->linker, guest_info);
 }
 
+acpi_add_table(table_offsets, tables_blob);
+build_iort(tables_blob, tables->linker, guest_info);
+
 /* RSDT is pointed to by RSDP */
 rsdt = tables_blob->len;
 build_rsdt(tables_blob, tables->linker, table_offsets, NULL, NULL);
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 850a962..d60f390 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -259,6 +259,90 @@ typedef struct AcpiFacsDescriptorRev1 
AcpiFacsDescriptorRev1;
  */
 
 /*
+ * IORT Table
+ */
+struct AcpiIortTable
+{
+ACPI_TABLE_HEADER_DEF /* ACPI common table header */
+uint32_t num_nodes;
+uint32_t node_offset;
+uint32_t reserved;
+} QEMU_PACKED;
+typedef struct AcpiIortTable AcpiIortTable;
+
+struct AcpiIortIdMapping
+{
+uint32_t input_base;
+uint32_t num_ids;
+uint32_t output_base;
+uint32_t output_ref;
+uint32_t flags;
+} QEMU_PACKED;
+typedef struct AcpiIortIdMapping AcpiIortIdMapping;
+
+struct AcpiIortNode
+{
+uint8_t  type;
+uint16_t length;
+uint8_t  revision;
+uint32_t reserved1;
+uint32_t num_id_maps;
+uint32_t id_array_offset;
+} QEMU_PACKED;
+typedef struct AcpiIortNode AcpiIortNode;
+
+struct AcpiIortSmmu2
+{
+AcpiIortNode iort_node;
+uint64_t base_addr;
+uint64_t span;
+uint32_t model;
+uint32_t flags;
+uint32_t gbl_intr_array_off;
+uint32_t ctx_intr_cnt;
+uint32_t ctx_intr_array_off;
+uint32_t pmr_intr_cnt;
+uint32_t pmr_intr_array_off;
+
+// Global interrupt array
+uint32_t gintr;
+uint32_t gintr_flags;
+uint32_t gcfgintr;
+uint32_t gcfgintr_flags;
+
+//AcpiIortIdMapping id_mapping_array[0];
+} QEMU_PACKED;
+typedef struct AcpiIortSmmu2 AcpiIortSmmu2;
+
+struct AcpiIortSmmu3
+{
+AcpiIortNode iort_node;
+uint64_t base_addr;
+uint32_t flags;
+uint32_t reserved2;
+uint64_t vatos_addr;
+uint32_t model;
+uint32_t event_irq;
+uint32_t pri_irq;
+uint32_t gerr_irq;
+uint32_t sync_irq;
+
+//AcpiIortIdMapping id_mapping_array[0];
+} QEMU_PACKED;
+typedef struct AcpiIortSmmu3 AcpiIortSmmu3;
+
+struct AcpiIortRC
+{
+AcpiIortNode iort_node;
+uint64_t mem_access_prop;
+uint32_t ats_attr;
+uint32_t pci_seg_num;
+
+AcpiIortIdMapping id_mapping_array[0];
+} QEMU_PACKED;
+typedef struct AcpiIortRC AcpiIortRC;
+
+/*
  * MADT values and structures
  */
 
-- 
2.9.3




[Qemu-devel] [PATCH v2 2/9] devicetree: Added new APIs to make use of more fdt functions

2016-08-22 Thread Prem Mallappa
SMMUv3 needs device tree entry like below

 interrupt-names = "gerror", "priq", "eventq", "cmdq-sync";

This patch introduces helper function to add entries like above

Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 device_tree.c| 35 +++
 include/sysemu/device_tree.h | 18 ++
 2 files changed, 53 insertions(+)

diff --git a/device_tree.c b/device_tree.c
index 6e06320..5d5966e 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -297,6 +297,24 @@ int qemu_fdt_setprop(void *fdt, const char *node_path,
 return r;
 }
 
+int qemu_fdt_appendprop(void *fdt, const char *node_path,
+ const char *property, const void *val, int size)
+{
+int r;
+
+r = fdt_appendprop(fdt, findnode_nofail(fdt, node_path), property,
+   val, size);
+if (r < 0) {
+error_report("%s: Couldn't set %s/%s: %s", __func__, node_path,
+ property, fdt_strerror(r));
+exit(1);
+}
+
+return r;
+}
+
+
+
 int qemu_fdt_setprop_cell(void *fdt, const char *node_path,
   const char *property, uint32_t val)
 {
@@ -319,6 +337,23 @@ int qemu_fdt_setprop_u64(void *fdt, const char *node_path,
 return qemu_fdt_setprop(fdt, node_path, property, , sizeof(val));
 }
 
+int qemu_fdt_appendprop_string(void *fdt, const char *node_path,
+const char *property, const char *string)
+{
+int r;
+
+r = fdt_appendprop_string(fdt, findnode_nofail(fdt, node_path),
+  property, string);
+if (r < 0) {
+error_report("%s: Couldn't set %s/%s = %s: %s", __func__,
+ node_path, property, string, fdt_strerror(r));
+exit(1);
+}
+
+return r;
+}
+
+
 int qemu_fdt_setprop_string(void *fdt, const char *node_path,
 const char *property, const char *string)
 {
diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h
index 705650a..5a0a297 100644
--- a/include/sysemu/device_tree.h
+++ b/include/sysemu/device_tree.h
@@ -45,12 +45,16 @@ char **qemu_fdt_node_path(void *fdt, const char *name, char 
*compat,
 
 int qemu_fdt_setprop(void *fdt, const char *node_path,
  const char *property, const void *val, int size);
+int qemu_fdt_appendprop(void *fdt, const char *node_path,
+ const char *property, const void *val, int size);
 int qemu_fdt_setprop_cell(void *fdt, const char *node_path,
   const char *property, uint32_t val);
 int qemu_fdt_setprop_u64(void *fdt, const char *node_path,
  const char *property, uint64_t val);
 int qemu_fdt_setprop_string(void *fdt, const char *node_path,
 const char *property, const char *string);
+int qemu_fdt_appendprop_string(void *fdt, const char *node_path,
+   const char *property, const char *string);
 int qemu_fdt_setprop_phandle(void *fdt, const char *node_path,
  const char *property,
  const char *target_node_path);
@@ -98,6 +102,20 @@ int qemu_fdt_add_subnode(void *fdt, const char *name);
  sizeof(qdt_tmp));\
 } while (0)
 
+
+#define qemu_fdt_appendprop_cells(fdt, node_path, property, ...)  \
+do {  \
+uint32_t qdt_tmp[] = { __VA_ARGS__ }; \
+int i;\
+  \
+for (i = 0; i < ARRAY_SIZE(qdt_tmp); i++) {   \
+qdt_tmp[i] = cpu_to_be32(qdt_tmp[i]); \
+} \
+qemu_fdt_appendprop(fdt, node_path, property, qdt_tmp,\
+ sizeof(qdt_tmp));\
+} while (0)
+
+
 void qemu_fdt_dumpdtb(void *fdt, int size);
 
 /**
-- 
2.9.3




[Qemu-devel] [PATCH v2 1/9] log: Add new IOMMU type

2016-08-22 Thread Prem Mallappa
Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 include/qemu/log.h | 1 +
 util/log.c | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/include/qemu/log.h b/include/qemu/log.h
index 234fa81..3dd2131 100644
--- a/include/qemu/log.h
+++ b/include/qemu/log.h
@@ -42,6 +42,7 @@ static inline bool qemu_log_separate(void)
 #define CPU_LOG_TB_NOCHAIN (1 << 13)
 #define CPU_LOG_PAGE   (1 << 14)
 #define LOG_TRACE  (1 << 15)
+#define CPU_LOG_IOMMU  (1 << 16)
 
 /* Returns true if a bit is set in the current loglevel mask
  */
diff --git a/util/log.c b/util/log.c
index 5ad72c1..62c4378 100644
--- a/util/log.c
+++ b/util/log.c
@@ -241,6 +241,8 @@ const QEMULogItem qemu_log_items[] = {
   "show CPU registers before entering a TB (lots of logs)" },
 { CPU_LOG_MMU, "mmu",
   "log MMU-related activities" },
+{ CPU_LOG_IOMMU, "iommu",
+  "log IOMMU-related activities" },
 { CPU_LOG_PCALL, "pcall",
   "x86 only: show protected mode far calls/returns/exceptions" },
 { CPU_LOG_RESET, "cpu_reset",
-- 
2.9.3




[Qemu-devel] [PATCH v2 7/9] [optional] tests: libqos: generic pci probing helpers

2016-08-22 Thread Prem Mallappa
Current libqos PCI helpers are x86 only, this addes a generic interface.

Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 tests/libqos/pci-generic.c | 197 +
 tests/libqos/pci-generic.h |  58 +
 2 files changed, 255 insertions(+)
 create mode 100644 tests/libqos/pci-generic.c
 create mode 100644 tests/libqos/pci-generic.h

diff --git a/tests/libqos/pci-generic.c b/tests/libqos/pci-generic.c
new file mode 100644
index 000..1820c0e
--- /dev/null
+++ b/tests/libqos/pci-generic.c
@@ -0,0 +1,197 @@
+/*
+ * libqos PCI bindings for non-PC
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aligu...@us.ibm.com>
+ *  Prem Mallappa <prem.malla...@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "libqos/pci-generic.h"
+
+#include "hw/pci/pci_regs.h"
+
+#include "qemu-common.h"
+#include "qemu/host-utils.h"
+
+#include 
+
+static uint8_t qpci_generic_io_readb(QPCIBus *bus, void *addr)
+{
+return readb((uintptr_t)addr);
+}
+
+static uint16_t qpci_generic_io_readw(QPCIBus *bus, void *addr)
+{
+return readw((uintptr_t)addr);
+}
+
+static uint32_t qpci_generic_io_readl(QPCIBus *bus, void *addr)
+{
+return readl((uintptr_t)addr);
+}
+
+static void qpci_generic_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
+{
+writeb((uintptr_t)addr, value);
+}
+
+static void qpci_generic_io_writew(QPCIBus *bus, void *addr, uint16_t value)
+{
+writew((uintptr_t)addr, value);
+}
+
+static void qpci_generic_io_writel(QPCIBus *bus, void *addr, uint32_t value)
+{
+writel((uintptr_t)addr, value);
+}
+
+#define devfn2addr(base, devfn, offset) \
+   ((base) | ((devfn) << 12) | (offset))
+
+#define bdf2offset(bus, devfn) \
+((bus) << 20 | (devfn) << 12)
+
+static uint8_t qpci_generic_config_readb(QPCIBus *bus, int devfn, uint8_t 
offset)
+{
+QPCIBusGen *s = container_of(bus, QPCIBusGen, bus);
+return readb(devfn2addr(s->base, devfn, offset));
+}
+
+static uint16_t qpci_generic_config_readw(QPCIBus *bus, int devfn, uint8_t 
offset)
+{ 
+QPCIBusGen *s = container_of(bus, QPCIBusGen, bus);
+return readw(devfn2addr(s->base, devfn, offset));
+}
+
+static uint32_t qpci_generic_config_readl(QPCIBus *bus, int devfn, uint8_t 
offset)
+{
+QPCIBusGen *s = container_of(bus, QPCIBusGen, bus);
+return readl(devfn2addr(s->base, devfn, offset));
+}
+
+static void qpci_generic_config_writeb(QPCIBus *bus, int devfn, uint8_t 
offset, uint8_t value)
+{
+QPCIBusGen *s = container_of(bus, QPCIBusGen, bus);
+writeb(devfn2addr(s->base, devfn, offset), value);
+}
+
+static void qpci_generic_config_writew(QPCIBus *bus, int devfn, uint8_t 
offset, uint16_t value)
+{
+QPCIBusGen *s = container_of(bus, QPCIBusGen, bus);
+writew(devfn2addr(s->base, devfn, offset), value);
+}
+
+static void qpci_generic_config_writel(QPCIBus *bus, int devfn, uint8_t 
offset, uint32_t value)
+{
+QPCIBusGen *s = container_of(bus, QPCIBusGen, bus);
+writel(devfn2addr(s->base, devfn, offset), value);
+}
+
+static void *qpci_generic_iomap(QPCIBus *bus, QPCIDevice *dev, int barno, 
uint64_t *sizeptr)
+{
+QPCIBusGen *s = container_of(bus, QPCIBusGen, bus);
+static const int bar_reg_map[] = {
+PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
+PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
+};
+int bar_reg;
+uint32_t addr;
+uint64_t size;
+uint32_t io_type;
+
+g_assert(barno >= 0 && barno <= 5);
+bar_reg = bar_reg_map[barno];
+
+qpci_config_writel(dev, bar_reg, 0x);
+addr = qpci_config_readl(dev, bar_reg);
+
+io_type = addr & PCI_BASE_ADDRESS_SPACE;
+if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
+addr &= PCI_BASE_ADDRESS_IO_MASK;
+} else {
+addr &= PCI_BASE_ADDRESS_MEM_MASK;
+}
+
+size = (1ULL << ctzl(addr));
+if (size == 0) {
+return NULL;
+}
+if (sizeptr) {
+*sizeptr = size;
+}
+
+if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
+uint16_t loc;
+
+g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
+ <= s->pci_iohole_size);
+s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
+loc = s->pci_iohole_start + s->pci_iohole_alloc;
+s->pci_iohole_alloc += size;
+
+qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
+
+return (void *)(intptr_t)loc;
+} else {
+uint64_t loc;
+
+g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
+ <= s->pci_hole_size);
+s->pci_hole_alloc = QEMU_ALIG

[Qemu-devel] [PATCH v2 5/9] hw: arm: Add SMMUv3 to virt platform, create DTS accordingly

2016-08-22 Thread Prem Mallappa
Default virt platform now creates SMMU device.
Default config to build SMMU device along is in previous patches.

Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 hw/arm/virt.c | 62 +++
 include/hw/arm/smmu.h | 33 +++
 include/hw/arm/virt.h |  2 ++
 3 files changed, 97 insertions(+)
 create mode 100644 include/hw/arm/smmu.h

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index c5c125e..f3c7891 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -57,6 +57,7 @@
 #include "hw/smbios/smbios.h"
 #include "qapi/visitor.h"
 #include "standard-headers/linux/input.h"
+#include "hw/arm/smmu.h"
 
 /* Number of external interrupt lines to configure the GIC with */
 #define NUM_IRQS 256
@@ -77,6 +78,7 @@ typedef struct VirtBoardInfo {
 uint32_t gic_phandle;
 uint32_t v2m_phandle;
 bool using_psci;
+uint32_t smmu_phandle;
 } VirtBoardInfo;
 
 typedef struct {
@@ -175,6 +177,7 @@ static const MemMapEntry a15memmap[] = {
 [VIRT_FW_CFG] = { 0x0902, 0x0018 },
 [VIRT_GPIO] =   { 0x0903, 0x1000 },
 [VIRT_SECURE_UART] ={ 0x0904, 0x1000 },
+[VIRT_SMMU] =   { 0x0905, 0x0002 }, /* 128K, needed */
 [VIRT_MMIO] =   { 0x0a00, 0x0200 },
 /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
 [VIRT_PLATFORM_BUS] =   { 0x0c00, 0x0200 },
@@ -195,9 +198,19 @@ static const int a15irqmap[] = {
 [VIRT_SECURE_UART] = 8,
 [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
 [VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */
+[VIRT_SMMU] = 74,/* ...to 74 + NUM_SMMU_IRQS - 1 */
 [VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */
 };
 
+static const struct smmuirq {
+const char *name;
+} smmuirqmap[NUM_SMMU_IRQS] = {
+[SMMU_IRQ_EVTQ] = {"eventq"},
+[SMMU_IRQ_PRIQ] = {"priq"},
+[SMMU_IRQ_CMD_SYNC] = {"cmdq-sync"},
+[SMMU_IRQ_GERROR] = {"gerror"},
+};
+
 static VirtBoardInfo machines[] = {
 {
 .cpu_model = "cortex-a15",
@@ -938,6 +951,50 @@ static void create_pcie_irq_map(const VirtBoardInfo *vbi, 
uint32_t gic_phandle,
0x7   /* PCI irq */);
 }
 
+static void alloc_smmu_phandle(VirtBoardInfo *vbi)
+{
+if (!vbi->smmu_phandle)
+vbi->smmu_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
+}
+
+static void create_smmu(VirtBoardInfo *vbi, qemu_irq *pic)
+{
+int i;
+char *smmu;
+const char compat[] = "arm,smmu-v3";
+int irq =  vbi->irqmap[VIRT_SMMU];
+hwaddr base = vbi->memmap[VIRT_SMMU].base;
+hwaddr size = vbi->memmap[VIRT_SMMU].size;
+int type = GIC_FDT_IRQ_TYPE_SPI;
+
+sysbus_create_varargs("smmuv3", base,
+  pic[irq],
+  pic[irq + 1],
+  pic[irq + 2],
+  pic[irq + 3],
+  NULL);
+
+smmu = g_strdup_printf("/smmuv3@%" PRIx64, base);
+qemu_fdt_add_subnode(vbi->fdt, smmu);
+qemu_fdt_setprop(vbi->fdt, smmu, "compatible", compat, sizeof(compat));
+qemu_fdt_setprop_sized_cells(vbi->fdt, smmu, "reg", 2, base, 2, size);
+
+for (i = 0; i < NUM_SMMU_IRQS; i++) {
+qemu_fdt_appendprop_cells(vbi->fdt, smmu, "interrupts",
+  type, irq + i,
+  GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+qemu_fdt_appendprop_string(vbi->fdt, smmu, "interrupt-names",
+   smmuirqmap[i].name);
+}
+
+qemu_fdt_setprop_cell(vbi->fdt, smmu, "clocks", vbi->clock_phandle);
+qemu_fdt_setprop_cell(vbi->fdt, smmu, "#iommu-cells", 0);
+qemu_fdt_setprop_string(vbi->fdt, smmu, "clock-names", "apb_pclk");
+
+qemu_fdt_setprop_cell(vbi->fdt, smmu, "phandle", vbi->smmu_phandle);
+g_free(smmu);
+}
+
 static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic,
 bool use_highmem)
 {
@@ -1048,6 +1105,7 @@ static void create_pcie(const VirtBoardInfo *vbi, 
qemu_irq *pic,
 }
 
 qemu_fdt_setprop_cell(vbi->fdt, nodename, "#interrupt-cells", 1);
+qemu_fdt_setprop_cells(vbi->fdt, nodename, "iommus", vbi->smmu_phandle);
 create_pcie_irq_map(vbi, vbi->gic_phandle, irq, nodename);
 
 g_free(nodename);
@@ -1332,8 +1390,12 @@ static void machvirt_init(MachineState *machine)
 
 create_rtc(vbi, pic);
 
+alloc_smmu_phandle(vbi);
+
 create_pcie(vbi, pic, vms->highmem);
 
+create_smmu(vbi, pic);
+
 create_gpio(vbi, pic);
 
 /* Create mmio transports, so the user can creat

[Qemu-devel] [PATCH v2 8/9] [optional] tests: SMMUv3 unit tests

2016-08-22 Thread Prem Mallappa
 - initializes SMMU device
 - initializes Test device
 - allocates page tables 1:1 mapping va == pa
 - allocates STE/CD accordingly for S1, S2, S1+S2
 - initiates DMA via PCI test device
 - verifies transfered data

Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 tests/Makefile.include |   4 +
 tests/smmuv3-test.c| 952 +
 2 files changed, 956 insertions(+)
 create mode 100644 tests/smmuv3-test.c

diff --git a/tests/Makefile.include b/tests/Makefile.include
index 7d63d16..08bee81 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -251,6 +251,8 @@ gcov-files-sparc-y += hw/timer/m48t59.c
 gcov-files-sparc64-y += hw/timer/m48t59.c
 check-qtest-arm-y = tests/tmp105-test$(EXESUF)
 check-qtest-arm-y = tests/ds1338-test$(EXESUF)
+check-qtest-aarch64-y += tests/smmuv3-test$(EXESUF)
+gcov-files-aarch64-y += hw/arm/smmu-v3.c
 gcov-files-arm-y += hw/misc/tmp105.c
 check-qtest-arm-y += tests/virtio-blk-test$(EXESUF)
 gcov-files-arm-y += arm-softmmu/hw/block/virtio-blk.c
@@ -535,6 +537,7 @@ tests/test-crypto-afsplit$(EXESUF): 
tests/test-crypto-afsplit.o $(test-crypto-ob
 tests/test-crypto-block$(EXESUF): tests/test-crypto-block.o 
$(test-crypto-obj-y)
 
 libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o tests/libqos/malloc.o
+libqos-obj-y += tests/libqos/pci-generic.o
 libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o
 libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o
 libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o
@@ -608,6 +611,7 @@ tests/test-filter-mirror$(EXESUF): 
tests/test-filter-mirror.o $(qtest-obj-y)
 tests/test-filter-redirector$(EXESUF): tests/test-filter-redirector.o 
$(qtest-obj-y)
 tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o 
contrib/ivshmem-server/ivshmem-server.o $(libqos-pc-obj-y)
 tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o
+tests/smmuv3-test$(EXESUF): tests/smmuv3-test.o $(libqos-obj-y) 
tests/libqos/malloc-generic.o
 
 ifeq ($(CONFIG_POSIX),y)
 LIBS += -lutil
diff --git a/tests/smmuv3-test.c b/tests/smmuv3-test.c
new file mode 100644
index 000..40837ef
--- /dev/null
+++ b/tests/smmuv3-test.c
@@ -0,0 +1,952 @@
+/*
+ * Copyright (C) 2014-2016 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Prem Mallappa <pmall...@broadcom.com>
+ *   <prem.malla...@gmail.com>
+ */
+
+#include "qemu/osdep.h"
+
+#include 
+#include 
+
+#include "libqtest.h"
+#include "libqos/libqos.h"
+#include "libqos/pci-generic.h"
+#include "libqos/malloc-generic.h"
+
+#include "qemu-common.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/pci/pci_regs.h"
+
+/* PCIe test device */
+#include "hw/misc/pci-testdev-smmu.h"
+
+/* SMMU */
+#include "hw/arm/smmu-common.h"
+#include "hw/arm/smmuv3-internal.h"
+
+
+/*
+ * STE/CD modification helpers
+ */
+#define ___SET(ste, off, start, len, val)   \
+({  \
+uint32_t *ptr = &(ste)->word[(off)];\
+*ptr = deposit32(*ptr, start, len, val);\
+})
+
+#define STE_SET_VALID(ste, val)   ___SET(ste, 0, 0, 1, val)
+#define STE_SET_CONFIG(ste, val)  ___SET(ste, 0, 1, 3, val)
+#define STE_SET_S1FMT(ste, val)   ___SET(ste, 0, 4, 2, val)
+#define STE_SET_S1CDMAX(ste, val) ___SET(ste, 1, 8, 2, val)
+#define STE_SET_EATS(ste, val)___SET(ste, 2, 28, 2, val)
+#define STE_SET_STRW(ste, val)___SET(ste, 2, 30, 2, val)
+#define STE_SET_S2VMID(ste, val)  ___SET(ste, 4, 0, 16, val) /* 4 */
+#define STE_SET_S2T0SZ(ste, val)  ___SET(ste, 5, 0, 6, val) /* 5 */
+#define STE_SET_S2TG(ste, val)___SET(ste, 5, 14, 2, val)
+#define STE_SET_S2PS(ste, val)___SET(ste, 5, 16, 3, val)
+#define STE_SET_S2AA64(ste, val)  ___SET(ste, 5, 19, 1, val)
+#define STE_SET_S2HD(ste, val)___SET(ste, 5, 24, 1, val)
+#define STE_SET_S2HA(ste, val)___SET(ste, 5, 25, 1, val)
+#define STE_SET_S2S(ste, val) ___SET(ste, 5, 26, 1, val)
+#define STE_SET_CTXPTR(ste, val)\
+({  \
+uint64_t __val = val;   \
+__val >>= 6;  

[Qemu-devel] [PATCH v2 0/9] SMMUv3 Emulation support

2016-08-22 Thread Prem Mallappa
v1 -> v2:
- Adopted review comments from Eric Auger
- Make SMMU_DPRINTF to internally call qemu_log
(since translation requests are too many, we need control
 on the type of log we want)
- SMMUTransCfg modified to suite simplicity
- Change RegInfo to uint64 register array
- Code cleanup
- Test cleanups
- Reshuffled patches

RFC -> v1:
- As per SMMUv3 spec 16.0 (only is_ste_consistant() is noticeable)
- Reworked register access/update logic
- Factored out translation code for
- single point bug fix
- sharing/removal in future
- (optional) Unit tests added, with PCI test device
- S1 with 4k/64k, S1+S2 with 4k/64k
- (S1 or S2) only can be verified by Linux 4.7 driver
- (optional) Priliminary ACPI support

RFC:
- Implements SMMUv3 spec 11.0
- Supported for PCIe devices, 
- Command Queue and Event Queue supported
- LPAE only, S1 is supported and Tested, S2 not tested
- BE mode Translation not supported
- IRQ support (legacy, no MSI)
- Tested with DPDK and e1000 

Patch 1: Add new log type for IOMMU transactions

Patch 2: Adds support in virt.c to create both SMMUv3 device and dts entries

Patch 2: Adds SMMUv3 model to QEMU
Multiple files, big ones, translate functionality is split across to
accomodate SMMUv2 model, and to remove when common translation feature
(if) becomes available.

Patch 3: Adds SMMU build support

Patch 4: Some devicetree function to add support for SMMU's multiple interrupt
 assignment with names

<< optional patches >>
Optional patches are posted for completeness or for those who wants to test.

Patch 5: A simple PCI device which does DMA from 'src' to 'dst' given
 src_addr, dst_addr and size, and is used by unit test, uses
 pci_dma_read and pci_dma_write in a crude way but serves the purpose.

Patch 6: Current libqos PCI helpers are x86 only, this addes a generic interface

Patch 7: Unit tests for SMMU, 
- initializes SMMU device 
- initializes Test device
- allocates page tables 1:1 mapping va == pa
- allocates STE/CD accordingly for S1, S2, S1+S2
- initiates DMA via PCI test device
- verifies transfered data

Patch 8: Added ACPI IORT tables, was needed for internal project purpose, but 
 posting here for anyone looking for testing ACPI on ARM platforms.
 (P.S: Linux side IORT patches are WIP)

Repo:
https://github.com/pmallappa/qemu/tree/upstream/smmuv3/v2

To Test:
$ make tests/smmuv3-test
$ QTEST_QEMU_BINARY=aarch64-softmmu/qemu-system-aarch64 tests/smmuv3-test
<< expect lot of prints >>

Any comments welcome..

Cheers
/Prem

Prem Mallappa (9):
  log: Add new IOMMU type
  devicetree: Added new APIs to make use of more fdt functions
  hw: arm: SMMUv3 emulation model
  hw: arm: Added SMMUv3 files for build
  hw: arm: Add SMMUv3 to virt platform, create DTS accordingly
  [optional] hw: misc: added testdev for smmu
  [optional] tests: libqos: generic pci probing helpers
  [optional] tests: SMMUv3 unit tests
  [optional] arm: smmu-v3: ACPI IORT initial support

 default-configs/aarch64-softmmu.mak |1 +
 device_tree.c   |   35 +
 hw/arm/Makefile.objs|1 +
 hw/arm/smmu-common.c|  152 
 hw/arm/smmu-common.h|  141 
 hw/arm/smmu-v3.c| 1369 +++
 hw/arm/smmuv3-internal.h|  432 +++
 hw/arm/virt-acpi-build.c|   43 ++
 hw/arm/virt.c   |   62 ++
 hw/misc/Makefile.objs   |2 +-
 hw/misc/pci-testdev-smmu.c  |  239 ++
 hw/misc/pci-testdev-smmu.h  |   22 +
 hw/vfio/common.c|2 +-
 include/hw/acpi/acpi-defs.h |   84 +++
 include/hw/arm/smmu.h   |   33 +
 include/hw/arm/virt.h   |2 +
 include/qemu/log.h  |1 +
 include/sysemu/device_tree.h|   18 +
 tests/Makefile.include  |4 +
 tests/libqos/pci-generic.c  |  197 +
 tests/libqos/pci-generic.h  |   58 ++
 tests/smmuv3-test.c |  952 
 util/log.c  |2 +
 23 files changed, 3850 insertions(+), 2 deletions(-)
 create mode 100644 hw/arm/smmu-common.c
 create mode 100644 hw/arm/smmu-common.h
 create mode 100644 hw/arm/smmu-v3.c
 create mode 100644 hw/arm/smmuv3-internal.h
 create mode 100644 hw/misc/pci-testdev-smmu.c
 create mode 100644 hw/misc/pci-testdev-smmu.h
 create mode 100644 include/hw/arm/smmu.h
 create mode 100644 tests/libqos/pci-generic.c
 create mode 100644 tests/lib

[Qemu-devel] [PATCH v2 6/9] [optional] hw: misc: added testdev for smmu

2016-08-22 Thread Prem Mallappa
A simple PCI device which does DMA from 'src' to 'dst' given
src_addr, dst_addr and size, and is used by unit test. uses
pci_dma_read and pci_dma_write in a crude way but serves the purpose.

Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 hw/misc/Makefile.objs  |   2 +-
 hw/misc/pci-testdev-smmu.c | 239 +
 hw/misc/pci-testdev-smmu.h |  22 +
 3 files changed, 262 insertions(+), 1 deletion(-)
 create mode 100644 hw/misc/pci-testdev-smmu.c
 create mode 100644 hw/misc/pci-testdev-smmu.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index ffb49c1..fc34c5f 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -29,7 +29,6 @@ obj-$(CONFIG_IMX) += imx_ccm.o
 obj-$(CONFIG_IMX) += imx31_ccm.o
 obj-$(CONFIG_IMX) += imx25_ccm.o
 obj-$(CONFIG_IMX) += imx6_ccm.o
-obj-$(CONFIG_IMX) += imx6_src.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
@@ -52,3 +51,4 @@ obj-$(CONFIG_PVPANIC) += pvpanic.o
 obj-$(CONFIG_EDU) += edu.o
 obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
 obj-$(CONFIG_AUX) += aux.o
+obj-$(CONFIG_ARM_SMMUV3) += pci-testdev-smmu.o
diff --git a/hw/misc/pci-testdev-smmu.c b/hw/misc/pci-testdev-smmu.c
new file mode 100644
index 000..b605912
--- /dev/null
+++ b/hw/misc/pci-testdev-smmu.c
@@ -0,0 +1,239 @@
+/*
+ * QEMU PCI test device
+ *
+ * Copyright (c) 2012 Red Hat Inc.
+ * Author: Michael S. Tsirkin <m...@redhat.com>
+ *
+ * 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/hw.h"
+#include "hw/pci/pci.h"
+#include "qemu/event_notifier.h"
+
+#include "pci-testdev-smmu.h"
+
+/*
+ * pci-testdev-smmu:
+ *  Simple PCIe device, to enable read and write from memory.
+ * Architecture:
+ *  Following registers are supported.
+ *  TST_COMMAND = 0x0
+ *  TST_STATUS  = 0x4
+ *  TST_SRC_ADDRESS = 0x8
+ *  TST_SIZE= 0x10
+ *  TST_DST_ADDRESS = 0x18
+ */
+#define PCI_TSTDEV_NREGS 0x10
+
+/*
+ *  TST_COMMAND Register bits
+ *  OP[0]
+ *  READ = 0x0
+ *  WRITE = 0x1
+ */
+
+struct RegInfo {
+uint64_t data;
+char *name;
+};
+typedef struct RegInfo RegInfo;
+
+typedef struct PCITestDevState {
+/*< private >*/
+PCIDevice dev;
+/*< public >*/
+
+MemoryRegion mmio;
+RegInfo regs[PCI_TSTDEV_NREGS];
+} PCITestDevState;
+
+#define TYPE_PCI_TEST_DEV "pci-testdev-smmu"
+
+#define PCI_TEST_DEV(obj) \
+OBJECT_CHECK(PCITestDevState, (obj), TYPE_PCI_TEST_DEV)
+
+static void
+pci_tstdev_reset(PCITestDevState *d)
+{
+memset(d->regs, 0, sizeof(d->regs));
+}
+
+static inline void
+pci_tstdev_write_reg(PCITestDevState *pdev, hwaddr addr, uint64_t val)
+{
+RegInfo *reg = >regs[addr >> 2];
+reg->data = val;
+}
+
+static inline uint32_t
+pci_tstdev_read32_reg(PCITestDevState *pdev, hwaddr addr)
+{
+RegInfo *reg = >regs[addr >> 2];
+return (uint32_t) reg->data;
+}
+
+static inline uint64_t
+pci_tstdev_read64_reg(PCITestDevState *pdev, hwaddr addr)
+{
+RegInfo *reg = >regs[addr >> 2];
+return reg->data;
+}
+
+static void
+pci_tstdev_handle_cmd(PCITestDevState *pdev, hwaddr addr, uint64_t val,
+unsigned _unused_size)
+{
+uint64_t s = pci_tstdev_read64_reg(pdev, TST_REG_SRC_ADDR);
+uint64_t d = pci_tstdev_read64_reg(pdev, TST_REG_DST_ADDR);
+uint32_t size = pci_tstdev_read32_reg(pdev, TST_REG_SIZE);
+uint8_t buf[128];
+
+printf("+> src:%lx, dst:%lx size:%d\n",
+   s, d, size);
+while (size) {
+int nbytes = (size < sizeof(buf)) ? size: sizeof(buf);
+int ret = 0;
+printf("nbytes:%d\n", nbytes);
+if (val & CMD_READ) {
+printf("doing pci_dma_read\n");
+ret = pci_dma_read(>dev, s, (void*)buf, nbytes);
+}
+if (ret)
+return;
+
+if (val & CMD_WRITE) {
+printf("doing pci_dma_write\n");
+ret = pci_dma_write(>dev, d, (void*)buf, nbytes);
+}
+size -= nbytes;
+s += nbytes;
+d

[Qemu-devel] [PATCH v2 4/9] hw: arm: Added SMMUv3 files for build

2016-08-22 Thread Prem Mallappa
Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 default-configs/aarch64-softmmu.mak | 1 +
 hw/arm/Makefile.objs| 1 +
 2 files changed, 2 insertions(+)

diff --git a/default-configs/aarch64-softmmu.mak 
b/default-configs/aarch64-softmmu.mak
index 2449483..83a2932 100644
--- a/default-configs/aarch64-softmmu.mak
+++ b/default-configs/aarch64-softmmu.mak
@@ -7,3 +7,4 @@ CONFIG_AUX=y
 CONFIG_DDC=y
 CONFIG_DPCD=y
 CONFIG_XLNX_ZYNQMP=y
+CONFIG_ARM_SMMUV3=y
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 12764ef..5207e99 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -18,3 +18,4 @@ obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
 obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
 obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
 obj-$(CONFIG_ASPEED_SOC) += ast2400.o palmetto-bmc.o
+obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmu-v3.o
-- 
2.9.3




Re: [Qemu-devel] [PATCH v1 1/8] hw: arm: SMMUv3 emulation model

2016-07-27 Thread Prem Mallappa

Hi Edger,
>
> A few first pass comments inline
>

Thanks for review.


>> +typedef struct SMMUTransCfg {
>> +union {
>> +hwaddr va;  /* Input to S1 */
>> +hwaddr ipa; /* Input to S2 */
>> +};
>
> I think we could just use va here.
>
Agreed

>> +union {
>> +hwaddr opa; /* Output from S2 */
>> +hwaddr pa;  /* Output from S1, Final PA */
>> +};
>
> ... and pa here.
Agreed

>
>> +
>> +bools2_needed;
>> +struct SMMUTransCfg *s2cfg;
>
> Can't we instead of having these fields tell the translate function
> what stage we are requesting translation for (and call translate
> twice for S1+S2)?
>
> That's more in line with what we do in the CPU models. Ultimately,
> it would be nice if we can gradually make the translation code
> more and more similar with the CPU one to the point where we
> can start sharing it.

I'll look into this, and change accordingly.

>
>> +} SMMUTransCfg;
>> +
>> +typedef struct {
>> +/*  */
>> +SysBusDeviceClass parent_class;
>> +
>> +/* public */
>> +SMMUTransErr (*translate)(SMMUTransCfg *cfg, uint32_t *pagesize,
>> +  uint32_t *perm, bool is_write);
>> +SMMUTransErr (*translate_lpae)(SMMUTransCfg *cfg, uint32_t 
*pagesize,

>> +   uint32_t *perm, bool is_write);
>
> I'm not sure about the naming here. In terms of SMMU, I've mostly heard
> the distinction between 32 and 64 bit page-tables and not really the term
> LPAE being used...
>
Will change it to translate_32, and translate_64, ARMv7 refers to it as 
LPAE in spec, hence the name.



>
>> +} SMMUBaseClass;
>> +
>> +#define SMMU_DEVICE_GET_CLASS(obj)  \
>> +OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_SMMU_DEV_BASE)
>> +
>> +/* #define ARM_SMMU_DEBUG */
>> +#ifdef ARM_SMMU_DEBUG
>> +
>> +extern uint32_t  dbg_bits;
>
>
> Can you please have a look at reusing qemu_log for this?
> There's a CPU_LOG_MMU classifier already, not sure if may
> want to introduce a CPU_LOG_IOMMU one. I'd be OK either
> way.
>
Sure, will make necessary changes.


>> +RegInfo  regs[SMMU_NREGS];
>
> This should be uint32_t I think. You can have a different
> RegisterInfo regs_info array if using the reg API.
>

My intensions were to use RegisterInfo, but it looked overkill for this 
particular case.


>> +
>> +static void smmu_write_reg(SMMUV3State *s, uint32_t addr, uint64_t val)
>> +{
>> +RegInfo *reg = >regs[addr >> 2];
>
> I think you should use the register API fully or not use it at all.
> You are kind of reimplementing some of it's features it seems.
> Have a look at hw/dma/xlnx-zynq-devcfg.c for an example on how it's done.
>
> IMO, this device doesn't benefit much from the register API though
> so I'd just probably have an array of uint32_t regs[SMMU_REGS] and
> deal with it. Either way is OK with me.
>
uint32_t was initial design, but it looked clumsy below is the code from 
earlier version (RFC)

Please see smmu_write_mmio() in
http://lists.nongnu.org/archive/html/qemu-devel/2016-01/msg01547.html

>
>> +
>> +reg->data = val;
>> +
>> +if (reg->post) {
>> +reg->post(reg, addr, val, s);
>> +}
>> +}
>> +
>> +#define smmu_write32_reg smmu_write_reg
>> +
>> +static inline uint32_t smmu_read32_reg(SMMUV3State *s, uint32_t addr)
>> +{
>> +RegInfo *reg = >regs[addr >> 2];
>> +
>> +return (uint32_t)reg->data;
>> +}
>> +
>> +static inline uint64_t smmu_read64_reg(SMMUV3State *s, uint32_t addr)
>> +{
>> +RegInfo *reg = >regs[addr >> 2];
>> +
>> +return reg->data;
>> +}
>
> You don't need this stuff with or without the register API. You can
> internally always access the regs directly by looking at 
s->regs[R_SOME_REG].


Probably not needed for the read path, but write() path is definitely 
made much cleaner. I'll see what I can do for direct access to registers.


Thanks
/Prem

<>



[Qemu-devel] [PATCH v1 7/8] [optional] tests: SMMUv3 unit tests

2016-06-23 Thread Prem Mallappa
 - initializes SMMU device
 - initializes Test device
 - allocates page tables 1:1 mapping va == pa
 - allocates STE/CD accordingly for S1, S2, S1+S2
 - initiates DMA via PCI test device
 - verifies transfered data

Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 tests/Makefile.include |   4 +
 tests/smmuv3-test.c| 905 +
 2 files changed, 909 insertions(+)
 create mode 100644 tests/smmuv3-test.c

diff --git a/tests/Makefile.include b/tests/Makefile.include
index 7d63d16..08bee81 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -251,6 +251,8 @@ gcov-files-sparc-y += hw/timer/m48t59.c
 gcov-files-sparc64-y += hw/timer/m48t59.c
 check-qtest-arm-y = tests/tmp105-test$(EXESUF)
 check-qtest-arm-y = tests/ds1338-test$(EXESUF)
+check-qtest-aarch64-y += tests/smmuv3-test$(EXESUF)
+gcov-files-aarch64-y += hw/arm/smmu-v3.c
 gcov-files-arm-y += hw/misc/tmp105.c
 check-qtest-arm-y += tests/virtio-blk-test$(EXESUF)
 gcov-files-arm-y += arm-softmmu/hw/block/virtio-blk.c
@@ -535,6 +537,7 @@ tests/test-crypto-afsplit$(EXESUF): 
tests/test-crypto-afsplit.o $(test-crypto-ob
 tests/test-crypto-block$(EXESUF): tests/test-crypto-block.o 
$(test-crypto-obj-y)
 
 libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o tests/libqos/malloc.o
+libqos-obj-y += tests/libqos/pci-generic.o
 libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o
 libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o
 libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o
@@ -608,6 +611,7 @@ tests/test-filter-mirror$(EXESUF): 
tests/test-filter-mirror.o $(qtest-obj-y)
 tests/test-filter-redirector$(EXESUF): tests/test-filter-redirector.o 
$(qtest-obj-y)
 tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o 
contrib/ivshmem-server/ivshmem-server.o $(libqos-pc-obj-y)
 tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o
+tests/smmuv3-test$(EXESUF): tests/smmuv3-test.o $(libqos-obj-y) 
tests/libqos/malloc-generic.o
 
 ifeq ($(CONFIG_POSIX),y)
 LIBS += -lutil
diff --git a/tests/smmuv3-test.c b/tests/smmuv3-test.c
new file mode 100644
index 000..dc8466b
--- /dev/null
+++ b/tests/smmuv3-test.c
@@ -0,0 +1,905 @@
+/*
+ * Copyright (C) 2014-2016 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Prem Mallappa <pmall...@broadcom.com>
+ *   <prem.malla...@gmail.com>
+ */
+
+#include "qemu/osdep.h"
+
+#include 
+#include 
+
+#include "libqtest.h"
+#include "libqos/libqos.h"
+#include "libqos/pci-generic.h"
+#include "libqos/malloc-generic.h"
+
+#include "qemu-common.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/pci/pci_regs.h"
+
+/* PCIe test device */
+#include "hw/misc/pci-testdev-smmu.h"
+
+/* SMMU */
+#include "hw/arm/smmu-common.h"
+#include "hw/arm/smmuv3-internal.h"
+
+
+/*
+ * STE/CD modification helpers
+ */
+#define ___SET(ste, off, start, len, val)   \
+({  \
+uint32_t *ptr = &(ste)->word[(off)];\
+*ptr = deposit32(*ptr, start, len, val);\
+})
+
+#define STE_SET_VALID(ste, val)   ___SET(ste, 0, 0, 1, val)
+#define STE_SET_CONFIG(ste, val)  ___SET(ste, 0, 1, 3, val)
+#define STE_SET_S1FMT(ste, val)   ___SET(ste, 0, 4, 2, val)
+#define STE_SET_S1CDMAX(ste, val) ___SET(ste, 1, 8, 2, val)
+#define STE_SET_EATS(ste, val)___SET(ste, 2, 28, 2, val)
+#define STE_SET_STRW(ste, val)___SET(ste, 2, 30, 2, val)
+#define STE_SET_S2VMID(ste, val)  ___SET(ste, 4, 0, 16, val) /* 4 */
+#define STE_SET_S2T0SZ(ste, val)  ___SET(ste, 5, 0, 6, val) /* 5 */
+#define STE_SET_S2TG(ste, val)___SET(ste, 5, 14, 2, val)
+#define STE_SET_S2PS(ste, val)___SET(ste, 5, 16, 3, val)
+#define STE_SET_S2AA64(ste, val)  ___SET(ste, 5, 19, 1, val)
+#define STE_SET_S2HD(ste, val)___SET(ste, 5, 24, 1, val)
+#define STE_SET_S2HA(ste, val)___SET(ste, 5, 25, 1, val)
+#define STE_SET_S2S(ste, val) ___SET(ste, 5, 26, 1, val)
+#define STE_SET_CTXPTR(ste, val)\
+({  \
+uint64_t __val = val;   \
+__val >>= 6;  

[Qemu-devel] [PATCH v1 5/8] [optional] hw: misc: added testdev for smmu

2016-06-23 Thread Prem Mallappa
A simple PCI device which does DMA from 'src' to 'dst' given
src_addr, dst_addr and size, and is used by unit test. uses
pci_dma_read and pci_dma_write in a crude way but serves the purpose.

Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 hw/misc/Makefile.objs  |   2 +-
 hw/misc/pci-testdev-smmu.c | 239 +
 hw/misc/pci-testdev-smmu.h |  22 +
 3 files changed, 262 insertions(+), 1 deletion(-)
 create mode 100644 hw/misc/pci-testdev-smmu.c
 create mode 100644 hw/misc/pci-testdev-smmu.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index ffb49c1..fc34c5f 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -29,7 +29,6 @@ obj-$(CONFIG_IMX) += imx_ccm.o
 obj-$(CONFIG_IMX) += imx31_ccm.o
 obj-$(CONFIG_IMX) += imx25_ccm.o
 obj-$(CONFIG_IMX) += imx6_ccm.o
-obj-$(CONFIG_IMX) += imx6_src.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
@@ -52,3 +51,4 @@ obj-$(CONFIG_PVPANIC) += pvpanic.o
 obj-$(CONFIG_EDU) += edu.o
 obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
 obj-$(CONFIG_AUX) += aux.o
+obj-$(CONFIG_ARM_SMMUV3) += pci-testdev-smmu.o
diff --git a/hw/misc/pci-testdev-smmu.c b/hw/misc/pci-testdev-smmu.c
new file mode 100644
index 000..52334eb
--- /dev/null
+++ b/hw/misc/pci-testdev-smmu.c
@@ -0,0 +1,239 @@
+/*
+ * QEMU PCI test device
+ *
+ * Copyright (c) 2012 Red Hat Inc.
+ * Author: Michael S. Tsirkin <m...@redhat.com>
+ *
+ * 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/hw.h"
+#include "hw/pci/pci.h"
+#include "qemu/event_notifier.h"
+
+#include "pci-testdev-smmu.h"
+
+/*
+ * pci-testdev-smmu:
+ *  Simple PCIe device, to enable read and write from memory.
+ * Architecture:
+ *  Following registers are supported.
+ *  TST_COMMAND = 0x0
+ *  TST_STATUS  = 0x4
+ *  TST_SRC_ADDRESS = 0x8
+ *  TST_SIZE= 0x10
+ *  TST_DST_ADDRESS = 0x18
+ */
+#define PCI_TSTDEV_NREGS 0x10
+
+/*
+ *  TST_COMMAND Register bits
+ *  OP[0]
+ *  READ = 0x0
+ *  WRITE = 0x1
+ */
+
+struct RegInfo {
+uint64_t data;
+char *name;
+};
+typedef struct RegInfo RegInfo;
+
+typedef struct PCITestDevState {
+/*< private >*/
+PCIDevice dev;
+/*< public >*/
+
+MemoryRegion mmio;
+RegInfo regs[PCI_TSTDEV_NREGS];
+} PCITestDevState;
+
+#define TYPE_PCI_TEST_DEV "pci-testdev-smmu"
+
+#define PCI_TEST_DEV(obj) \
+OBJECT_CHECK(PCITestDevState, (obj), TYPE_PCI_TEST_DEV)
+
+static void
+pci_tstdev_reset(PCITestDevState *d)
+{
+memset(d->regs, 0, sizeof(d->regs));
+}
+
+static inline void
+pci_tstdev_write_reg(PCITestDevState *pdev, hwaddr addr, uint64_t val)
+{
+RegInfo *reg = >regs[addr >> 2];
+reg->data = val;
+}
+
+static inline uint32_t
+pci_tstdev_read32_reg(PCITestDevState *pdev, hwaddr addr)
+{
+RegInfo *reg = >regs[addr >> 2];
+return (uint32_t) reg->data;
+}
+
+static inline uint64_t
+pci_tstdev_read64_reg(PCITestDevState *pdev, hwaddr addr)
+{
+RegInfo *reg = >regs[addr >> 2];
+return reg->data;
+}
+
+static void
+pci_tstdev_handle_cmd(PCITestDevState *pdev, hwaddr addr, uint64_t val,
+unsigned _unused_size)
+{
+uint64_t s = pci_tstdev_read64_reg(pdev, TST_REG_SRC_ADDR);
+uint64_t d = pci_tstdev_read64_reg(pdev, TST_REG_DST_ADDR);
+uint32_t size = pci_tstdev_read32_reg(pdev, TST_REG_SIZE);
+uint8_t buf[128];
+
+printf("+> src:%lx, dst:%lx size:%d\n",
+   s, d, size);
+while (size) {
+int nbytes = (size < sizeof(buf)) ? size: sizeof(buf);
+int ret = 0;
+printf("nbytes:%d\n", nbytes);
+if (val & CMD_READ) {
+printf("doing pci_dma_read\n");
+ret = pci_dma_read(>dev, s, (void*)buf, nbytes);
+}
+if (ret)
+return;
+
+if (val & CMD_WRITE) {
+printf("doing pci_dma_write\n");
+ret = pci_dma_write(>dev, d, (void*)buf, nbytes);
+}
+size -= nbytes;
+s += nbytes;
+d

[Qemu-devel] [PATCH v1 4/8] hw: arm: Add SMMUv3 to virt platform, create DTS accordingly

2016-06-23 Thread Prem Mallappa
Default virt platform now creates SMMU device.
Default config to build SMMU device along is in previous patches.

Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 hw/arm/virt.c | 62 +++
 include/hw/arm/smmu.h | 33 +++
 include/hw/arm/virt.h |  2 ++
 3 files changed, 97 insertions(+)
 create mode 100644 include/hw/arm/smmu.h

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index c5c125e..f3c7891 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -57,6 +57,7 @@
 #include "hw/smbios/smbios.h"
 #include "qapi/visitor.h"
 #include "standard-headers/linux/input.h"
+#include "hw/arm/smmu.h"
 
 /* Number of external interrupt lines to configure the GIC with */
 #define NUM_IRQS 256
@@ -77,6 +78,7 @@ typedef struct VirtBoardInfo {
 uint32_t gic_phandle;
 uint32_t v2m_phandle;
 bool using_psci;
+uint32_t smmu_phandle;
 } VirtBoardInfo;
 
 typedef struct {
@@ -175,6 +177,7 @@ static const MemMapEntry a15memmap[] = {
 [VIRT_FW_CFG] = { 0x0902, 0x0018 },
 [VIRT_GPIO] =   { 0x0903, 0x1000 },
 [VIRT_SECURE_UART] ={ 0x0904, 0x1000 },
+[VIRT_SMMU] =   { 0x0905, 0x0002 }, /* 128K, needed */
 [VIRT_MMIO] =   { 0x0a00, 0x0200 },
 /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
 [VIRT_PLATFORM_BUS] =   { 0x0c00, 0x0200 },
@@ -195,9 +198,19 @@ static const int a15irqmap[] = {
 [VIRT_SECURE_UART] = 8,
 [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
 [VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */
+[VIRT_SMMU] = 74,/* ...to 74 + NUM_SMMU_IRQS - 1 */
 [VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */
 };
 
+static const struct smmuirq {
+const char *name;
+} smmuirqmap[NUM_SMMU_IRQS] = {
+[SMMU_IRQ_EVTQ] = {"eventq"},
+[SMMU_IRQ_PRIQ] = {"priq"},
+[SMMU_IRQ_CMD_SYNC] = {"cmdq-sync"},
+[SMMU_IRQ_GERROR] = {"gerror"},
+};
+
 static VirtBoardInfo machines[] = {
 {
 .cpu_model = "cortex-a15",
@@ -938,6 +951,50 @@ static void create_pcie_irq_map(const VirtBoardInfo *vbi, 
uint32_t gic_phandle,
0x7   /* PCI irq */);
 }
 
+static void alloc_smmu_phandle(VirtBoardInfo *vbi)
+{
+if (!vbi->smmu_phandle)
+vbi->smmu_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
+}
+
+static void create_smmu(VirtBoardInfo *vbi, qemu_irq *pic)
+{
+int i;
+char *smmu;
+const char compat[] = "arm,smmu-v3";
+int irq =  vbi->irqmap[VIRT_SMMU];
+hwaddr base = vbi->memmap[VIRT_SMMU].base;
+hwaddr size = vbi->memmap[VIRT_SMMU].size;
+int type = GIC_FDT_IRQ_TYPE_SPI;
+
+sysbus_create_varargs("smmuv3", base,
+  pic[irq],
+  pic[irq + 1],
+  pic[irq + 2],
+  pic[irq + 3],
+  NULL);
+
+smmu = g_strdup_printf("/smmuv3@%" PRIx64, base);
+qemu_fdt_add_subnode(vbi->fdt, smmu);
+qemu_fdt_setprop(vbi->fdt, smmu, "compatible", compat, sizeof(compat));
+qemu_fdt_setprop_sized_cells(vbi->fdt, smmu, "reg", 2, base, 2, size);
+
+for (i = 0; i < NUM_SMMU_IRQS; i++) {
+qemu_fdt_appendprop_cells(vbi->fdt, smmu, "interrupts",
+  type, irq + i,
+  GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+qemu_fdt_appendprop_string(vbi->fdt, smmu, "interrupt-names",
+   smmuirqmap[i].name);
+}
+
+qemu_fdt_setprop_cell(vbi->fdt, smmu, "clocks", vbi->clock_phandle);
+qemu_fdt_setprop_cell(vbi->fdt, smmu, "#iommu-cells", 0);
+qemu_fdt_setprop_string(vbi->fdt, smmu, "clock-names", "apb_pclk");
+
+qemu_fdt_setprop_cell(vbi->fdt, smmu, "phandle", vbi->smmu_phandle);
+g_free(smmu);
+}
+
 static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic,
 bool use_highmem)
 {
@@ -1048,6 +1105,7 @@ static void create_pcie(const VirtBoardInfo *vbi, 
qemu_irq *pic,
 }
 
 qemu_fdt_setprop_cell(vbi->fdt, nodename, "#interrupt-cells", 1);
+qemu_fdt_setprop_cells(vbi->fdt, nodename, "iommus", vbi->smmu_phandle);
 create_pcie_irq_map(vbi, vbi->gic_phandle, irq, nodename);
 
 g_free(nodename);
@@ -1332,8 +1390,12 @@ static void machvirt_init(MachineState *machine)
 
 create_rtc(vbi, pic);
 
+alloc_smmu_phandle(vbi);
+
 create_pcie(vbi, pic, vms->highmem);
 
+create_smmu(vbi, pic);
+
 create_gpio(vbi, pic);
 
 /* Create mmio transports, so the user can creat

[Qemu-devel] [PATCH v1 8/8] [optional] arm: smmu-v3: ACPI IORT initial support

2016-06-23 Thread Prem Mallappa
Added ACPI IORT tables, was needed for internal project purpose, but
posting here for anyone looking for testing ACPI on ARM platforms.
(P.S: Linux side IORT patches are WIP)

Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 hw/arm/virt-acpi-build.c| 43 +++
 include/hw/acpi/acpi-defs.h | 84 +
 2 files changed, 127 insertions(+)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 1fa0581..d5fb69e 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -382,6 +382,45 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, 
unsigned rsdt_tbl_offset)
 return rsdp_table;
 }
 
+/*
+ * TODO: Simple IORT for now, will add ID mappings as we go
+ * basic idea is to instantiate SMMU from ACPI
+ */
+static void
+build_iort(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
+{
+int iort_start = table_data->len;
+AcpiIortTable *iort;
+AcpiIortNode *iort_node;
+AcpiIortSmmu3 *smmu;
+AcpiIortRC *rc;
+const MemMapEntry *memmap = guest_info->memmap;
+
+iort = acpi_data_push(table_data, sizeof(*iort));
+
+iort->length = sizeof(*iort);
+iort->node_offset = table_data->len - iort_start;
+iort->num_nodes++;
+
+smmu = acpi_data_push(table_data, sizeof(*smmu));
+iort_node = >iort_node;
+iort_node->type = 0x04;  /* SMMUv3 */
+iort_node->length = sizeof(*smmu);
+smmu->base_addr = cpu_to_le64(memmap[VIRT_SMMU].base);
+
+iort->num_nodes++;
+
+rc = acpi_data_push(table_data, sizeof(*rc));
+iort_node = >iort_node;
+iort_node->type = 0x02;  /* RC */
+iort_node->length = sizeof(*rc);
+rc->ats_attr = 1;
+rc->pci_seg_num = 0;
+
+build_header(linker, table_data, (void *)(table_data->data + iort_start),
+ "IORT", table_data->len - iort_start, 0, NULL, NULL);
+}
+
 static void
 build_spcr(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
 {
@@ -667,6 +706,7 @@ void virt_acpi_build(VirtGuestInfo *guest_info, 
AcpiBuildTables *tables)
  * MADT
  * MCFG
  * DSDT
+ * IORT = ACPI 6.0
  */
 
 /* DSDT is pointed to by FADT */
@@ -694,6 +734,9 @@ void virt_acpi_build(VirtGuestInfo *guest_info, 
AcpiBuildTables *tables)
 build_srat(tables_blob, tables->linker, guest_info);
 }
 
+acpi_add_table(table_offsets, tables_blob);
+build_iort(tables_blob, tables->linker, guest_info);
+
 /* RSDT is pointed to by RSDP */
 rsdt = tables_blob->len;
 build_rsdt(tables_blob, tables->linker, table_offsets, NULL, NULL);
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 850a962..d60f390 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -259,6 +259,90 @@ typedef struct AcpiFacsDescriptorRev1 
AcpiFacsDescriptorRev1;
  */
 
 /*
+ * IORT Table
+ */
+struct AcpiIortTable
+{
+ACPI_TABLE_HEADER_DEF /* ACPI common table header */
+uint32_t num_nodes;
+uint32_t node_offset;
+uint32_t reserved;
+} QEMU_PACKED;
+typedef struct AcpiIortTable AcpiIortTable;
+
+struct AcpiIortIdMapping
+{
+uint32_t input_base;
+uint32_t num_ids;
+uint32_t output_base;
+uint32_t output_ref;
+uint32_t flags;
+} QEMU_PACKED;
+typedef struct AcpiIortIdMapping AcpiIortIdMapping;
+
+struct AcpiIortNode
+{
+uint8_t  type;
+uint16_t length;
+uint8_t  revision;
+uint32_t reserved1;
+uint32_t num_id_maps;
+uint32_t id_array_offset;
+} QEMU_PACKED;
+typedef struct AcpiIortNode AcpiIortNode;
+
+struct AcpiIortSmmu2
+{
+AcpiIortNode iort_node;
+uint64_t base_addr;
+uint64_t span;
+uint32_t model;
+uint32_t flags;
+uint32_t gbl_intr_array_off;
+uint32_t ctx_intr_cnt;
+uint32_t ctx_intr_array_off;
+uint32_t pmr_intr_cnt;
+uint32_t pmr_intr_array_off;
+
+// Global interrupt array
+uint32_t gintr;
+uint32_t gintr_flags;
+uint32_t gcfgintr;
+uint32_t gcfgintr_flags;
+
+//AcpiIortIdMapping id_mapping_array[0];
+} QEMU_PACKED;
+typedef struct AcpiIortSmmu2 AcpiIortSmmu2;
+
+struct AcpiIortSmmu3
+{
+AcpiIortNode iort_node;
+uint64_t base_addr;
+uint32_t flags;
+uint32_t reserved2;
+uint64_t vatos_addr;
+uint32_t model;
+uint32_t event_irq;
+uint32_t pri_irq;
+uint32_t gerr_irq;
+uint32_t sync_irq;
+
+//AcpiIortIdMapping id_mapping_array[0];
+} QEMU_PACKED;
+typedef struct AcpiIortSmmu3 AcpiIortSmmu3;
+
+struct AcpiIortRC
+{
+AcpiIortNode iort_node;
+uint64_t mem_access_prop;
+uint32_t ats_attr;
+uint32_t pci_seg_num;
+
+AcpiIortIdMapping id_mapping_array[0];
+} QEMU_PACKED;
+typedef struct AcpiIortRC AcpiIortRC;
+
+/*
  * MADT values and structures
  */
 
-- 
2.9.0




[Qemu-devel] [PATCH v1 6/8] [optional] tests: libqos: generic pci probing helpers

2016-06-23 Thread Prem Mallappa
Current libqos PCI helpers are x86 only, this addes a generic interface.

Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 tests/libqos/pci-generic.c | 197 +
 tests/libqos/pci-generic.h |  58 +
 2 files changed, 255 insertions(+)
 create mode 100644 tests/libqos/pci-generic.c
 create mode 100644 tests/libqos/pci-generic.h

diff --git a/tests/libqos/pci-generic.c b/tests/libqos/pci-generic.c
new file mode 100644
index 000..1820c0e
--- /dev/null
+++ b/tests/libqos/pci-generic.c
@@ -0,0 +1,197 @@
+/*
+ * libqos PCI bindings for non-PC
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aligu...@us.ibm.com>
+ *  Prem Mallappa <prem.malla...@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "libqos/pci-generic.h"
+
+#include "hw/pci/pci_regs.h"
+
+#include "qemu-common.h"
+#include "qemu/host-utils.h"
+
+#include 
+
+static uint8_t qpci_generic_io_readb(QPCIBus *bus, void *addr)
+{
+return readb((uintptr_t)addr);
+}
+
+static uint16_t qpci_generic_io_readw(QPCIBus *bus, void *addr)
+{
+return readw((uintptr_t)addr);
+}
+
+static uint32_t qpci_generic_io_readl(QPCIBus *bus, void *addr)
+{
+return readl((uintptr_t)addr);
+}
+
+static void qpci_generic_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
+{
+writeb((uintptr_t)addr, value);
+}
+
+static void qpci_generic_io_writew(QPCIBus *bus, void *addr, uint16_t value)
+{
+writew((uintptr_t)addr, value);
+}
+
+static void qpci_generic_io_writel(QPCIBus *bus, void *addr, uint32_t value)
+{
+writel((uintptr_t)addr, value);
+}
+
+#define devfn2addr(base, devfn, offset) \
+   ((base) | ((devfn) << 12) | (offset))
+
+#define bdf2offset(bus, devfn) \
+((bus) << 20 | (devfn) << 12)
+
+static uint8_t qpci_generic_config_readb(QPCIBus *bus, int devfn, uint8_t 
offset)
+{
+QPCIBusGen *s = container_of(bus, QPCIBusGen, bus);
+return readb(devfn2addr(s->base, devfn, offset));
+}
+
+static uint16_t qpci_generic_config_readw(QPCIBus *bus, int devfn, uint8_t 
offset)
+{ 
+QPCIBusGen *s = container_of(bus, QPCIBusGen, bus);
+return readw(devfn2addr(s->base, devfn, offset));
+}
+
+static uint32_t qpci_generic_config_readl(QPCIBus *bus, int devfn, uint8_t 
offset)
+{
+QPCIBusGen *s = container_of(bus, QPCIBusGen, bus);
+return readl(devfn2addr(s->base, devfn, offset));
+}
+
+static void qpci_generic_config_writeb(QPCIBus *bus, int devfn, uint8_t 
offset, uint8_t value)
+{
+QPCIBusGen *s = container_of(bus, QPCIBusGen, bus);
+writeb(devfn2addr(s->base, devfn, offset), value);
+}
+
+static void qpci_generic_config_writew(QPCIBus *bus, int devfn, uint8_t 
offset, uint16_t value)
+{
+QPCIBusGen *s = container_of(bus, QPCIBusGen, bus);
+writew(devfn2addr(s->base, devfn, offset), value);
+}
+
+static void qpci_generic_config_writel(QPCIBus *bus, int devfn, uint8_t 
offset, uint32_t value)
+{
+QPCIBusGen *s = container_of(bus, QPCIBusGen, bus);
+writel(devfn2addr(s->base, devfn, offset), value);
+}
+
+static void *qpci_generic_iomap(QPCIBus *bus, QPCIDevice *dev, int barno, 
uint64_t *sizeptr)
+{
+QPCIBusGen *s = container_of(bus, QPCIBusGen, bus);
+static const int bar_reg_map[] = {
+PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
+PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
+};
+int bar_reg;
+uint32_t addr;
+uint64_t size;
+uint32_t io_type;
+
+g_assert(barno >= 0 && barno <= 5);
+bar_reg = bar_reg_map[barno];
+
+qpci_config_writel(dev, bar_reg, 0x);
+addr = qpci_config_readl(dev, bar_reg);
+
+io_type = addr & PCI_BASE_ADDRESS_SPACE;
+if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
+addr &= PCI_BASE_ADDRESS_IO_MASK;
+} else {
+addr &= PCI_BASE_ADDRESS_MEM_MASK;
+}
+
+size = (1ULL << ctzl(addr));
+if (size == 0) {
+return NULL;
+}
+if (sizeptr) {
+*sizeptr = size;
+}
+
+if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
+uint16_t loc;
+
+g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
+ <= s->pci_iohole_size);
+s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
+loc = s->pci_iohole_start + s->pci_iohole_alloc;
+s->pci_iohole_alloc += size;
+
+qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
+
+return (void *)(intptr_t)loc;
+} else {
+uint64_t loc;
+
+g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
+ <= s->pci_hole_size);
+s->pci_hole_alloc = QEMU_ALIG

[Qemu-devel] [PATCH v1 2/8] hw: arm: Added SMMUv3 files for build

2016-06-23 Thread Prem Mallappa
Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 default-configs/aarch64-softmmu.mak | 1 +
 hw/arm/Makefile.objs| 1 +
 2 files changed, 2 insertions(+)

diff --git a/default-configs/aarch64-softmmu.mak 
b/default-configs/aarch64-softmmu.mak
index 2449483..83a2932 100644
--- a/default-configs/aarch64-softmmu.mak
+++ b/default-configs/aarch64-softmmu.mak
@@ -7,3 +7,4 @@ CONFIG_AUX=y
 CONFIG_DDC=y
 CONFIG_DPCD=y
 CONFIG_XLNX_ZYNQMP=y
+CONFIG_ARM_SMMUV3=y
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 12764ef..5207e99 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -18,3 +18,4 @@ obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
 obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
 obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
 obj-$(CONFIG_ASPEED_SOC) += ast2400.o palmetto-bmc.o
+obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmu-v3.o
-- 
2.9.0




[Qemu-devel] [PATCH v1 3/8] devicetree: Added new APIs to make use of more fdt functions

2016-06-23 Thread Prem Mallappa
SMMUv3 needs device tree entry like below

 interrupt-names = "gerror", "priq", "eventq", "cmdq-sync";

This patch introduces helper function to add entries like above

Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 device_tree.c| 35 +++
 include/sysemu/device_tree.h | 18 ++
 2 files changed, 53 insertions(+)

diff --git a/device_tree.c b/device_tree.c
index 6e06320..5d5966e 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -297,6 +297,24 @@ int qemu_fdt_setprop(void *fdt, const char *node_path,
 return r;
 }
 
+int qemu_fdt_appendprop(void *fdt, const char *node_path,
+ const char *property, const void *val, int size)
+{
+int r;
+
+r = fdt_appendprop(fdt, findnode_nofail(fdt, node_path), property,
+   val, size);
+if (r < 0) {
+error_report("%s: Couldn't set %s/%s: %s", __func__, node_path,
+ property, fdt_strerror(r));
+exit(1);
+}
+
+return r;
+}
+
+
+
 int qemu_fdt_setprop_cell(void *fdt, const char *node_path,
   const char *property, uint32_t val)
 {
@@ -319,6 +337,23 @@ int qemu_fdt_setprop_u64(void *fdt, const char *node_path,
 return qemu_fdt_setprop(fdt, node_path, property, , sizeof(val));
 }
 
+int qemu_fdt_appendprop_string(void *fdt, const char *node_path,
+const char *property, const char *string)
+{
+int r;
+
+r = fdt_appendprop_string(fdt, findnode_nofail(fdt, node_path),
+  property, string);
+if (r < 0) {
+error_report("%s: Couldn't set %s/%s = %s: %s", __func__,
+ node_path, property, string, fdt_strerror(r));
+exit(1);
+}
+
+return r;
+}
+
+
 int qemu_fdt_setprop_string(void *fdt, const char *node_path,
 const char *property, const char *string)
 {
diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h
index 705650a..5a0a297 100644
--- a/include/sysemu/device_tree.h
+++ b/include/sysemu/device_tree.h
@@ -45,12 +45,16 @@ char **qemu_fdt_node_path(void *fdt, const char *name, char 
*compat,
 
 int qemu_fdt_setprop(void *fdt, const char *node_path,
  const char *property, const void *val, int size);
+int qemu_fdt_appendprop(void *fdt, const char *node_path,
+ const char *property, const void *val, int size);
 int qemu_fdt_setprop_cell(void *fdt, const char *node_path,
   const char *property, uint32_t val);
 int qemu_fdt_setprop_u64(void *fdt, const char *node_path,
  const char *property, uint64_t val);
 int qemu_fdt_setprop_string(void *fdt, const char *node_path,
 const char *property, const char *string);
+int qemu_fdt_appendprop_string(void *fdt, const char *node_path,
+   const char *property, const char *string);
 int qemu_fdt_setprop_phandle(void *fdt, const char *node_path,
  const char *property,
  const char *target_node_path);
@@ -98,6 +102,20 @@ int qemu_fdt_add_subnode(void *fdt, const char *name);
  sizeof(qdt_tmp));\
 } while (0)
 
+
+#define qemu_fdt_appendprop_cells(fdt, node_path, property, ...)  \
+do {  \
+uint32_t qdt_tmp[] = { __VA_ARGS__ }; \
+int i;\
+  \
+for (i = 0; i < ARRAY_SIZE(qdt_tmp); i++) {   \
+qdt_tmp[i] = cpu_to_be32(qdt_tmp[i]); \
+} \
+qemu_fdt_appendprop(fdt, node_path, property, qdt_tmp,\
+ sizeof(qdt_tmp));\
+} while (0)
+
+
 void qemu_fdt_dumpdtb(void *fdt, int size);
 
 /**
-- 
2.9.0




[Qemu-devel] [PATCH v1 1/8] hw: arm: SMMUv3 emulation model

2016-06-23 Thread Prem Mallappa
Big patch adds SMMUv3 model to Qemu
  - As per SMMUv3 spec 16.0
  - Works with SMMUv3 driver in Linux 4.7rc1
  - Only LPAE mode translation supported
  - BE mode is not supported yet
  - Stage1, Stage2 and S1+S2
  - Suspend/resume not tested

Signed-off-by: Prem Mallappa <prem.malla...@broadcom.com>
---
 hw/arm/smmu-common.c |  142 +
 hw/arm/smmu-common.h |  135 +
 hw/arm/smmu-v3.c | 1461 ++
 hw/arm/smmuv3-internal.h |  417 +
 4 files changed, 2155 insertions(+)
 create mode 100644 hw/arm/smmu-common.c
 create mode 100644 hw/arm/smmu-common.h
 create mode 100644 hw/arm/smmu-v3.c
 create mode 100644 hw/arm/smmuv3-internal.h

diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
new file mode 100644
index 000..e4bb61c
--- /dev/null
+++ b/hw/arm/smmu-common.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2014-2016 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Prem Mallappa <pmall...@broadcom.com>
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "sysemu/sysemu.h"
+#include "exec/address-spaces.h"
+
+#include "smmu-common.h"
+
+inline MemTxResult smmu_read_sysmem(hwaddr addr, void *buf, int len)
+{
+switch (len) {
+case 4:
+*(uint32_t *)buf = ldl_le_phys(_space_memory, addr);
+break;
+case 8:
+*(uint64_t *)buf = ldq_le_phys(_space_memory, addr);
+break;
+default:
+return address_space_rw(_space_memory, addr,
+MEMTXATTRS_UNSPECIFIED, buf, len, false);
+}
+return MEMTX_OK;
+}
+
+inline void
+smmu_write_sysmem(hwaddr addr, void *buf, int len)
+{
+switch (len) {
+case 4:
+stl_le_phys(_space_memory, addr, *(uint32_t *)buf);
+break;
+case 8:
+stq_le_phys(_space_memory, addr, *(uint64_t *)buf);
+break;
+default:
+address_space_rw(_space_memory, addr,
+ MEMTXATTRS_UNSPECIFIED, buf, len, true);
+}
+}
+
+SMMUTransErr
+smmu_translate_lpae(SMMUTransCfg *cfg, uint32_t *pagesize,
+uint32_t *perm, bool is_write)
+{
+int ret, level;
+int granule_sz = cfg->granule_sz;
+int va_size = cfg->va_size;
+hwaddr  va, addr, mask;
+hwaddr *outaddr;
+
+va = addr = cfg->va;/* or ipa in Stage2 */
+
+assert(va_size == 64);  /* We dont support 32-bit yet */
+/* same location, for clearity */
+outaddr = cfg->s2_needed ? >opa : >pa;
+
+level = 4 - (va_size - cfg->tsz - 4) / granule_sz;
+
+mask = (1ULL << (granule_sz + 3)) - 1;
+
+addr = extract64(cfg->ttbr, 0, 48);
+addr &= ~((1ULL << (va_size - cfg->tsz - (granule_sz * (4 - level - 1);
+
+for (;;) {
+uint64_t desc;
+#ifdef SMMU_DEBUG
+uint64_t ored = (va >> (granule_sz * (4 - level))) & mask;
+SMMU_DPRINTF(TT_1,
+ "Level: %d va:%lx addr:%lx ored:%lx\n",
+ level, va, addr, ored);
+#endif
+addr |= (va >> (granule_sz * (4 - level))) & mask;
+addr &= ~7ULL;
+
+if (smmu_read_sysmem(addr, , sizeof(desc))) {
+ret = SMMU_TRANS_ERR_WALK_EXT_ABRT;
+SMMU_DPRINTF(CRIT, "Translation table read error lvl:%d\n", level);
+break;
+}
+
+SMMU_DPRINTF(TT_1,
+ "Level: %d gran_sz:%d mask:%lx addr:%lx desc:%lx\n",
+ level, granule_sz, mask, addr, desc);
+
+if (!(desc & 1) ||
+(!(desc & 2) && (level == 3))) {
+ret = SMMU_TRANS_ERR_TRANS;
+break;
+}
+
+/* We call again to resolve address at this 'level' */
+if (cfg->s2_needed) {
+uint32_t perm_s2, pagesize_s2;
+SMMUTransCfg *s2cfg = cfg->s2cfg;
+
+s2cfg->ipa = desc;
+
+ret = smmu_translate_lpae(s2cfg, _s2,
+  _s2, is_write);
+if (ret) {
+break;
+}
+
+desc = (uint64_t)s2cfg->opa;
+SMMU_DPRINTF(TT_2, "addr:%lx pagesize:%x\n", addr, *pagesize);
+}
+
+addr = desc & 0x000ULL;
+

[Qemu-devel] [PATCH v1 0/8] SMMUv3 Emulation support

2016-06-23 Thread Prem Mallappa
RFC -> v1:
- As per SMMUv3 spec 16.0 (only is_ste_consistant() is noticeable)
- Reworked register access/update logic
- Factored out translation code for
- single point bug fix
- sharing/removal in future
- (optional) Unit tests added, with PCI test device
- S1 with 4k/64k, S1+S2 with 4k/64k
- (S1 or S2) only can be verified by Linux 4.7 driver
- (optional) Priliminary ACPI support

RFC:
- Implements SMMUv3 spec 11.0
- Supported for PCIe devices, 
- Command Queue and Event Queue supported
- LPAE only, S1 is supported and Tested, S2 not tested
- BE mode Translation not supported
- IRQ support (legacy, no MSI)
- Tested with DPDK and e1000 

Patch 1: Adds SMMUv3 model to QEMU
Multiple files, big ones, translate functionality is split across to
accomodate SMMUv2 model, and to remove when common translation feature
(if) becomes available.

Patch 2: Adds SMMU build support

Patch 3: Some devicetree function to add support for SMMU's multiple interrupt
 assignment with names

Patch 4: Adds support in virt.c to create both SMMUv3 device and dts entries

<< optional patches >>
Optional patches are posted for completeness or for those who wants to test.

Patch 5: A simple PCI device which does DMA from 'src' to 'dst' given
 src_addr, dst_addr and size, and is used by unit test, uses
 pci_dma_read and pci_dma_write in a crude way but serves the purpose.

Patch 6: Current libqos PCI helpers are x86 only, this addes a generic interface

Patch 7: Unit tests for SMMU, 
- initializes SMMU device 
- initializes Test device
- allocates page tables 1:1 mapping va == pa
- allocates STE/CD accordingly for S1, S2, S1+S2
- initiates DMA via PCI test device
- verifies transfered data

Patch 8: Added ACPI IORT tables, was needed for internal project purpose, but 
 posting here for anyone looking for testing ACPI on ARM platforms.
 (P.S: Linux side IORT patches are WIP)

Repo:
https://github.com/pmallappa/qemu/tree/develop

To Test:
$ make tests/smmuv3-test
$ QTEST_QEMU_BINARY=aarch64-softmmu/qemu-system-aarch64 tests/smmuv3-test
<< expect lot of prints >>

Any comments welcome..

Cheers
/Prem

Prem Mallappa (8):
  hw: arm: SMMUv3 emulation model
  hw: arm: Added SMMUv3 files for build
  devicetree: Added new APIs to make use of more fdt functions
  hw: arm: Add SMMUv3 to virt platform, create DTS accordingly
  [optional] hw: misc: added testdev for smmu
  [optional] tests: libqos: generic pci probing helpers
  [optional] tests: SMMUv3 unit tests
  [optional] arm: smmu-v3: ACPI IORT initial support

 default-configs/aarch64-softmmu.mak |1 +
 device_tree.c   |   35 +
 hw/arm/Makefile.objs|1 +
 hw/arm/smmu-common.c|  142 
 hw/arm/smmu-common.h|  135 
 hw/arm/smmu-v3.c| 1461 +++
 hw/arm/smmuv3-internal.h|  417 ++
 hw/arm/virt-acpi-build.c|   43 ++
 hw/arm/virt.c   |   62 ++
 hw/misc/Makefile.objs   |2 +-
 hw/misc/pci-testdev-smmu.c  |  239 ++
 hw/misc/pci-testdev-smmu.h  |   22 +
 include/hw/acpi/acpi-defs.h |   84 ++
 include/hw/arm/smmu.h   |   33 +
 include/hw/arm/virt.h   |2 +
 include/sysemu/device_tree.h|   18 +
 tests/Makefile.include  |4 +
 tests/libqos/pci-generic.c  |  197 +
 tests/libqos/pci-generic.h  |   58 ++
 tests/smmuv3-test.c |  905 ++
 20 files changed, 3860 insertions(+), 1 deletion(-)
 create mode 100644 hw/arm/smmu-common.c
 create mode 100644 hw/arm/smmu-common.h
 create mode 100644 hw/arm/smmu-v3.c
 create mode 100644 hw/arm/smmuv3-internal.h
 create mode 100644 hw/misc/pci-testdev-smmu.c
 create mode 100644 hw/misc/pci-testdev-smmu.h
 create mode 100644 include/hw/arm/smmu.h
 create mode 100644 tests/libqos/pci-generic.c
 create mode 100644 tests/libqos/pci-generic.h
 create mode 100644 tests/smmuv3-test.c

-- 
2.9.0



Re: [Qemu-devel] [PATCH RFC 0/4] ARM SMMUv3 Emulation

2016-04-04 Thread Prem Mallappa
Hi Peter,
Thanks for following up.

I got access to 16.0 version, I dont particularly see any difference in
basic functionality.

I had been in touch with Edger, We agreed upon making usable code b/w
smmuv2 and smmuv3 for now. Currently the code is in working state.

I also heard, there has been talks to merge code with CPU's page walk code.
but till then we can make use of the current setup.

I'll be sending out v2 soon, just trying to write some Qtests to test
2-stage page walks.

Edger, if you already have written Qtest code please do share, it would be
of tremendous help now.


Thanks

On Mon, Apr 4, 2016 at 4:38 PM, Peter Maydell <peter.mayd...@linaro.org>
wrote:

> On 17 February 2016 at 04:39, Prem Mallappa <prem.malla...@broadcom.com>
> wrote:
> > Hi Peter,
> >
> > I have access till
> > "PRD03-GENC-010952 Version 11.0" updated 18/04/15.
> >
> > infocenter.arm.com has only SMMUv2 made public
> >
> > Please let me know if there is a new version available
> >  - to public.
> >  - through channels, I have to work with my organizational contact to
> get to
> > the new one.
> >
> > I am not expecting any fundamental operation changes. However, I'll take
> a
> > look if theres a new version.
>
> Hi; just wanted to ask if you'd got the updated SMMUv3 spec yet,
> and to check that there that we're in agreement that the next step
> here is that you would do a respin of your patches updated to the
> final specification. (That is, you're not blocked waiting for
> anything more from me or Edgar. Occasionally in these patch review
> threads there's a miscommunication and both sides think they're
> waiting for the other, so I just wanted to check that.)
>
> thanks
> -- PMM
>



-- 
Cheers,
/Prem


Re: [Qemu-devel] [PATCH RFC 0/4] ARM SMMUv3 Emulation

2016-02-16 Thread Prem Mallappa
Hi Peter,

I have access till
"PRD03-GENC-010952 Version 11.0" updated 18/04/15.

infocenter.arm.com has only SMMUv2 made public

Please let me know if there is a new version available
 - to public.
 - through channels, I have to work with my organizational contact to get
to the new one.

I am not expecting any fundamental operation changes. However, I'll take a
look if theres a new version.

Cheers,
/Prem


On Tue, Feb 16, 2016 at 4:20 PM, Peter Maydell <peter.mayd...@linaro.org>
wrote:

> On 11 January 2016 at 14:16,  <pmall...@broadcom.com> wrote:
> > From: Prem Mallappa <pmall...@broadcom.com>
> >
> > Implementation Notes:
> >
> > - SMMUv3 model, as per ARM SMMUv3 11.0 spec
>
> I haven't reviewed any of this yet, but 11.0 is not the current
> revision of the SMMUv3 spec, so you should probably start by
> updating your code to the current version. Otherwise code review
> will be full of "this isn't what the spec says"...
>
> thanks
> -- PMM
>



-- 
Cheers,
/Prem


Re: [Qemu-devel] [RFC PATCH 0/5] Introduce Intel 82574 GbE Controller Emulation (e1000e)

2016-01-12 Thread Prem Mallappa

On 10/25/2015 10:30 PM, Leonid Bloch wrote:

Hello qemu-devel,

This patch series is an RFC for the new networking device emulation
we're developing for QEMU.


Thanks for the patch

/Prem

Tested By: Prem Mallappa <pmall...@broadcom.com>