[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [v2 4/6] xen/iommu: smmu-v3: Add Xen specific code to enable the ported driver
On 5/30/2018 10:10 PM, Manish Jaggi wrote: > > > On 05/31/2018 01:16 AM, Sameer Goel wrote: >> Manish, I'll take another look at the variable names. I might not have >> enough time :). >>>> >>>> On 05/23/2018 10:48 PM, Manish Jaggi wrote: >>>>> Hi Sameer, >>>>> >>>>> General Comment, please use appropriate variable names for XXX_domain >>>>> structures in code which is xen specific. >>>> I thought that we had discussed this before on one of the RFCs. >>> Yes and no one replied to my last comment that the var names have to be non >>> confusing in Xen specific code. >> I'm sorry about that. I just assumed that since the policy on ported >> variable names was consistent we so not nee to change the names. >> >>>> At this point we are just using the format used for smmu-v2. >>> smmu-v2 has a lot of confusing variable names with _domain. >>> I believe that file needs to be fixed as well. >>>> I don't think that the variable names are inappropriate. Unless there is a >>>> very specific issue with the variable names, >>> The issue is in code readability and understanding the flow. >>> It is confusing so many _domain variable names are used which are not >>> verbose. >> These names are coming from the original Linux code. So, we do not change >> them as per the policy. That being said I can add a comment section to >> explain the confusing variables in the Xen specific code? Please let me know >> if this will help us resolve this issue? >> > If it is in Xen specific functions, then it can be changed, this is what > julien also confirmed. Agreed. Changing the var names. > >>> Two functions different and confusing variable names >>>>>> + struct iommu_domain *domain; >>>>>> +}; >>>>>> + >>>>> As this is a xen specific code, can the variable names be used >>>>> appropriately. >>>>> Repeating my comment from earlier version. >>>>> a domain is usually a VM in Xen. So it is a bit confusing to use domain >>>>> for iommu_domain. >> The struct is fine but you have an issue with the var name right? > Yes. >> >>>>>> +/* >>>>>> + * Xen: io_pgtable compatibility defines. >>>>>> + * Most of these are to port in the S1 translation code as is. >>>>>> + */ >>>>>> +struct io_pgtable_ops { >>>>>> +}; >>>>>> + >>>>>> +struct iommu_gather_ops { >>>>>> + void (*tlb_flush_all)(void *cookie); >>>>>> + void (*tlb_add_flush)(unsigned long iova, size_t size, size_t >>>>>> granule, >>>>>> + bool leaf, void *cookie); >>>>>> + void (*tlb_sync)(void *cookie); >>>>>> +}; >>>>>> + >>>>>> +struct io_pgtable_cfg { >>>>>> + /* >>>>>> + * IO_PGTABLE_QUIRK_ARM_NS: (ARM formats) Set NS and NSTABLE bits in >>>>>> + * stage 1 PTEs, for hardware which insists on validating them >>>>>> + * even in non-secure state where they should normally be >>>>>> ignored. >>>>>> + * >>>>>> + * IO_PGTABLE_QUIRK_NO_PERMS: Ignore the IOMMU_READ, IOMMU_WRITE and >>>>>> + * IOMMU_NOEXEC flags and map everything with full access, for >>>>>> + * hardware which does not implement the permissions of a given >>>>>> + * format, and/or requires some format-specific default value. >>>>>> + * >>>>>> + * IO_PGTABLE_QUIRK_TLBI_ON_MAP: If the format forbids caching >>>>>> invalid >>>>>> + * (unmapped) entries but the hardware might do so anyway, >>>>>> perform >>>>>> + * TLB maintenance when mapping as well as when unmapping. >>>>>> + * >>>>>> + * IO_PGTABLE_QUIRK_ARM_MTK_4GB: (ARM v7s format) Set bit 9 in all >>>>>> + * PTEs, for Mediatek IOMMUs which treat it as a 33rd address bit >>>>>> + * when the SoC is in "4GB mode" and they can only access the >>>>>> high >>>>>> + * remap of DRAM (0x1_00000000 to 0x1_ffffffff). >>>>>> + * >>>>>> + * IO_PGTABLE_QUIRK_NO_DMA: Guarantees that the tables will only >>>>>> ever >>>>>> + * be accessed by a fully cache-coherent IOMMU or CPU (e.g. for a >>>>>> + * software-emulated IOMMU), such that pagetable updates need not >>>>>> + * be treated as explicit DMA data. >>>>>> + */ >>>>>> + #define IO_PGTABLE_QUIRK_ARM_NS BIT(0) >>>>>> + #define IO_PGTABLE_QUIRK_NO_PERMS BIT(1) >>>>>> + #define IO_PGTABLE_QUIRK_TLBI_ON_MAP BIT(2) >>>>>> + #define IO_PGTABLE_QUIRK_ARM_MTK_4GB BIT(3) >>>>>> + #define IO_PGTABLE_QUIRK_NO_DMA BIT(4) >>>>>> + unsigned long quirks; >>>>>> + unsigned long pgsize_bitmap; >>>>>> + unsigned int ias; >>>>>> + unsigned int oas; >>>>>> + const struct iommu_gather_ops *tlb; >>>>>> + struct device *iommu_dev; >>>>>> + >>>>>> + /* Low-level data specific to the table format */ >>>>>> + union { >>>>>> + struct { >>>>>> + u64 ttbr[2]; >>>>>> + u64 tcr; >>>>>> + u64 mair[2]; >>>>>> + } arm_lpae_s1_cfg; >>>>>> + >>>>>> + struct { >>>>>> + u64 vttbr; >>>>>> + u64 vtcr; >>>>>> + } arm_lpae_s2_cfg; >>>>>> + >>>>>> + struct { >>>>>> + u32 ttbr[2]; >>>>>> + u32 tcr; >>>>>> + u32 nmrr; >>>>>> + u32 prrr; >>>>>> + } arm_v7s_cfg; >>>>>> + }; >>>>>> +}; >>>>>> + >>>>>> +enum io_pgtable_fmt { >>>>>> + ARM_32_LPAE_S1, >>>>>> + ARM_32_LPAE_S2, >>>>>> + ARM_64_LPAE_S1, >>>>>> + ARM_64_LPAE_S2, >>>>>> + ARM_V7S, >>>>>> + IO_PGTABLE_NUM_FMTS, >>>>>> +}; >>>>>> + >>>>>> +/* >>>>>> + * Xen: The pgtable_ops are used by the S1 translations, so return the >>>>>> dummy >>>>>> + * address. >>>>>> + */ >>>>>> +#define alloc_io_pgtable_ops(f, c, o) ((struct io_pgtable_ops *)0x1) >>>>>> +#define free_io_pgtable_ops(o) >>>>>> + >>>>>> +/* Xen: Define wrapper for requesting IRQs */ >>>>>> +#define IRQF_ONESHOT 0 >>>>>> + >>>>>> +typedef void (*irq_handler_t)(int, void *, struct cpu_user_regs *); >>>>>> + >>>>>> +static inline int devm_request_irq(struct device *dev, unsigned int irq, >>>>>> + irq_handler_t handler, unsigned long irqflags, >>>>>> + const char *devname, void *dev_id) >>>>>> +{ >>>>>> + /* >>>>>> + * SMMUv3 implementation can support wired interrupt outputs that >>>>>> are >>>>>> + * edge-triggered. Set the irq type as per the spec. >>>>>> + */ >>>>>> + irq_set_type(irq, IRQ_TYPE_EDGE_BOTH); >>>>>> + return request_irq(irq, irqflags, handler, devname, dev_id); >>>>>> +} >>>>>> + >>>>>> +/* >>>>>> + * Xen does not have a concept of threaded irq, but we can use tasklets >>>>>> to >>>>>> + * achieve the desired functionality as needed. >>>>>> + */ >>>>>> +int devm_request_threaded_irq(struct device *dev, unsigned int irq, >>>>>> irq_handler_t handler, >>>>>> + irq_handler_t thread_fn, unsigned long irqflags, >>>>>> + const char *devname, void *dev_id) >>>>>> +{ >>>>>> + return devm_request_irq(dev, irq, thread_fn, irqflags, devname, >>>>>> dev_id); >>>>>> +} >>>>>> + >>>>>> +/* Xen: The mutex is used only during initialization so the typecast is >>>>>> safe */ >>>>>> +#define mutex spinlock >>>>>> +#define mutex_init spin_lock_init >>>>>> +#define mutex_lock spin_lock >>>>>> +#define mutex_unlock spin_unlock >>>>>> + >>>>>> +#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us) \ >>>>>> +({ \ >>>>>> + s_time_t deadline = NOW() + MICROSECS(timeout_us); \ >>>>>> + for (;;) { \ >>>>>> + (val) = op(addr); \ >>>>>> + if (cond) \ >>>>>> + break; \ >>>>>> + if (NOW() > deadline) { \ >>>>>> + (val) = op(addr); \ >>>>>> + break; \ >>>>>> + } \ >>>>>> + udelay(sleep_us); \ >>>>>> + } \ >>>>>> + (cond) ? 0 : -ETIMEDOUT; \ >>>>>> +}) >>>>>> + >>>>>> +#define readl_relaxed_poll_timeout(addr, val, cond, delay_us, >>>>>> timeout_us) \ >>>>>> + readx_poll_timeout(readl_relaxed, addr, val, cond, delay_us, >>>>>> timeout_us) >>>>>> + >>>>>> +#define VA_BITS 0 /* Only needed for S1 translations */ >>>>>> /* MMIO registers */ >>>>>> #define ARM_SMMU_IDR0 0x0 >>>>>> @@ -433,6 +819,7 @@ enum pri_resp { >>>>>> PRI_RESP_SUCC, >>>>>> }; >>>>>> +#if 0 /* Xen: No MSI support in this iteration */ >>>>>> enum arm_smmu_msi_index { >>>>>> EVTQ_MSI_INDEX, >>>>>> GERROR_MSI_INDEX, >>>>>> @@ -457,6 +844,7 @@ static phys_addr_t >>>>>> arm_smmu_msi_cfg[ARM_SMMU_MAX_MSIS][3] = { >>>>>> ARM_SMMU_PRIQ_IRQ_CFG2, >>>>>> }, >>>>>> }; >>>>>> +#endif >>>>>> struct arm_smmu_cmdq_ent { >>>>>> /* Common fields */ >>>>>> @@ -561,6 +949,8 @@ struct arm_smmu_s2_cfg { >>>>>> u16 vmid; >>>>>> u64 vttbr; >>>>>> u64 vtcr; >>>>>> + /* Xen: Domain associated to this configuration */ >>>>>> + struct domain *domain; >>>>>> }; >>>>>> struct arm_smmu_strtab_ent { >>>>>> @@ -635,9 +1025,25 @@ struct arm_smmu_device { >>>>>> struct arm_smmu_strtab_cfg strtab_cfg; >>>>>> /* IOMMU core code handle */ >>>>>> +#if 0 /*Xen: Generic iommu_device ref not needed here */ >>>>>> struct iommu_device iommu; >>>>>> +#endif >>>>> Is it clean to put #if 0, can this line be deleted or used with a proper >>>>> macro >> Manish this is a var name from original struct from Linux. I have just >> followed the prior standard of adding #if 0. > It does not look clean, can we use something other than 0, say a macro > NA_CODE ... That's true. Adding NA_CODE will probably make things clearer. I'll incorporate the change. >>>>>> + /* Xen: Need to keep a list of SMMU devices */ >>>>>> + struct list_head devices; >>>>>> + /* Xen: Tasklets for handling evts/faults and pci page request >>>>>> IRQs*/ >>>>>> + struct tasklet evtq_tasklet; >>>>>> + struct tasklet priq_tasklet; >>>>>> + struct tasklet combined_irq_tasklet; ..... >>>>>> + struct device *dev) >>>>> This is returning iommu_domain and not a domain. >>>>> Please change the name of function. >> Same as smmu-v2.c. I think with the complexity of the code we should try to >> get this in as the prior code. Once the set that has been pending for some >> time is in. We can start on the variable cleanup activity. I say this so >> that we can make the names consistent across the drivers and this will be a >> lot easier to do when the majority of the other code is in. > smmu-v2.c had this issue and I had hard time understanding the code, the > confusing variable names break the understanding flow, especially when you > are debugging something and have lost touch of code. > So let not do same mistake as in smmu-v2.c Agreed. Will change the variable name. >>>>>> +{ >>>>>> + struct iommu_domain *domain; >>>>>> + struct arm_smmu_xen_domain *xen_domain; >>>>> A suggestion >>>>> 1. as you have used in above function smmu_domain variable for >>>>> arm_smmu_xen_domain >>>>> Can similar logic be used for iommu_domain. >> I am fine changing the var name. >>>>> 2. When smmu_domain variable name is used in above function why >>>>> xen_domain is used in this function. >>>>> It is quite confusing. >>>>> logically xen_domain should mean a VM. >> You lost me man. xen_domain is referring to the page tables of the the VM >> currently using the SMMU. What is the concern? > in xen when you read basic documentation a domain is a VM, right? > Now what would xen_domain variable should mean. > How would you know it has something to do with SMMU. > > So it is confusing to someone looking at the code. I agree that you would think about the VMs when you see xen_domain. In this case the xen_domain variable has a 1:1 correspondence with the SMMU. If I call this smmu_xen_domain will it be easier to read? >>>>>> + struct arm_smmu_device *smmu; >>>>>> + struct arm_smmu_domain *smmu_domain; >>>>> smmu_domain was used for arm_smmu_xen_domain. >> Failed to see it. But, I'll have another look. >> >>>>> consistency of variable names is necessary for code clarity >>>>>> + >>>>>> + xen_domain = dom_iommu(d)->arch.priv; >>>>>> + >>>>>> + smmu = arm_smmu_get_by_fwnode(dev->iommu_fwspec->iommu_fwnode); >>>>>> + if (!smmu) >>>>>> + return NULL; >>>>>> + >>>>>> + /* >>>>>> + * Loop through the &xen_domain->contexts to locate a context >>>>>> + * assigned to this SMMU >>>>>> + */ >>>>>> + list_for_each_entry(domain, &xen_domain->contexts, list) { >>>>>> + smmu_domain = to_smmu_domain(domain); >>>>>> + if (smmu_domain->smmu == smmu) >>>>>> + return domain; >>>>>> + } >>>>>> + >>>>>> + return NULL; >>>>>> +} >>>>>> + >>>>>> +static void arm_smmu_destroy_iommu_domain(struct iommu_domain *domain) >>>>> same >> Ok >>>>>> +{ >>>>>> + list_del(&domain->list); >>>>>> + arm_smmu_domain_free(domain); >>>>>> +} >>>>>> + >>>>>> +static int arm_smmu_assign_dev(struct domain *d, u8 devfn, >>>>>> + struct device *dev, u32 flag) >>>>>> +{ >>>>>> + int ret = 0; >>>>>> + struct iommu_domain *domain; >>>>>> + struct arm_smmu_xen_domain *xen_domain; >>>>> same >> xen_domain is fine. You have an issue with the iommu_domioan here? > domain has a variable name d, and iommu_domain has a variable name domain. > Isnt it confusing. > Why cant we use > struct iommu_domain *io_domain ... I agree. I am changing this all to iommu_domain. io_domain is fine too. What do you prefer? > >>>>>> + struct arm_smmu_domain *arm_smmu; >>>>>> + >>>>>> + xen_domain = dom_iommu(d)->arch.priv; >>>>>> + >>>>>> + if (!dev->archdata.iommu) { >>>>>> + dev->archdata.iommu = xzalloc(struct arm_smmu_xen_device); >>>>>> + if (!dev->archdata.iommu) >>>>>> + return -ENOMEM; >>>>>> + } >>>>>> + >>>>>> + ret = arm_smmu_add_device(dev); >>>>>> + if (ret) >>>>>> + return ret; >>>>>> + >>>>>> + spin_lock(&xen_domain->lock); >>>>>> + >>>>>> + /* >>>>>> + * Check to see if an iommu_domain already exists for this xen >>>>>> domain >>>>>> + * under the same SMMU >>>>>> + */ >>>>>> + domain = arm_smmu_get_domain(d, dev); >>>>>> + if (!domain) { >>>>>> + >>>>>> + domain = arm_smmu_domain_alloc(IOMMU_DOMAIN_DMA); >>>>>> + if (!domain) { >>>>>> + ret = -ENOMEM; >>>>>> + goto out; >>>>>> + } >>>>>> + >>>>>> + arm_smmu = to_smmu_domain(domain); >>>>>> + arm_smmu->s2_cfg.domain = d; >>>>>> + >>>>>> + /* Chain the new context to the domain */ >>>>>> + list_add(&domain->list, &xen_domain->contexts); >>>>>> + >>>>>> + } >>>>>> + >>>>>> + ret = arm_smmu_attach_dev(domain, dev); >>>>>> + if (ret) { >>>>>> + if (domain->ref.counter == 0) >>>>>> + arm_smmu_destroy_iommu_domain(domain); >>>>>> + } else { >>>>>> + atomic_inc(&domain->ref); >>>>>> + } >>>>>> + >>>>>> +out: >>>>>> + spin_unlock(&xen_domain->lock); >>>>>> + return ret; >>>>>> +} >>>>>> + >>>>>> +static int arm_smmu_deassign_dev(struct domain *d, struct device *dev) >>>>>> +{ >>>>>> + struct iommu_domain *domain = arm_smmu_get_domain(d, dev); >>>>>> + struct arm_smmu_xen_domain *xen_domain; >>>>>> + struct arm_smmu_domain *arm_smmu = to_smmu_domain(domain); >>>>> same >>>>>> + >>>>>> + xen_domain = dom_iommu(d)->arch.priv; >>>>>> + >>>>>> + if (!arm_smmu || arm_smmu->s2_cfg.domain != d) { >>>>>> + dev_err(dev, " not attached to domain %d\n", d->domain_id); >>>>>> + return -ESRCH; >>>>>> + } >>>>>> + >>>>>> + spin_lock(&xen_domain->lock); >>>>>> + >>>>>> + arm_smmu_detach_dev(dev); >>>>>> + atomic_dec(&domain->ref); >>>>>> + >>>>>> + if (domain->ref.counter == 0) >>>>>> + arm_smmu_destroy_iommu_domain(domain); >>>>>> + >>>>>> + spin_unlock(&xen_domain->lock); >>>>>> + >>>>>> + return 0; >>>>>> +} >>>>>> + >>>>>> +static int arm_smmu_reassign_dev(struct domain *s, struct domain *t, >>>>>> + u8 devfn, struct device *dev) >>>>>> +{ >>>>>> + int ret = 0; >>>>>> + >>>>>> + /* Don't allow remapping on other domain than hwdom */ >>>>>> + if (t && t != hardware_domain) >>>>>> + return -EPERM; >>>>>> + >>>>>> + if (t == s) >>>>>> + return 0; >>>>>> + >>>>>> + ret = arm_smmu_deassign_dev(s, dev); >>>>>> + if (ret) >>>>>> + return ret; >>>>>> + >>>>>> + if (t) { >>>>>> + /* No flags are defined for ARM. */ >>>>>> + ret = arm_smmu_assign_dev(t, devfn, dev, 0); >>>>>> + if (ret) >>>>>> + return ret; >>>>>> + } >>>>>> + >>>>>> + return 0; >>>>>> +} >>>>>> + >>>>>> +static int arm_smmu_iommu_domain_init(struct domain *d) >>>>> Where is iommu_domain initialized? >>>>> The function does not use a iommu_domain * variable >>>>>> +{ >>>>>> + struct arm_smmu_xen_domain *xen_domain; >>>>>> + >>>>>> + xen_domain = xzalloc(struct arm_smmu_xen_domain); >>>>>> + if (!xen_domain) >>>>>> + return -ENOMEM; >>>>>> + >>>>>> + spin_lock_init(&xen_domain->lock); >>>>>> + INIT_LIST_HEAD(&xen_domain->contexts); >>>>>> + >>>>>> + dom_iommu(d)->arch.priv = xen_domain; >>>>>> + >>>>>> + return 0; >>>>>> +} >>>>>> + >>>>>> +static void __hwdom_init arm_smmu_iommu_hwdom_init(struct domain *d) >>>>>> +{ >>>>>> +} >>>>>> + >>>>>> +static void arm_smmu_iommu_domain_teardown(struct domain *d) >>>>>> +{ >>>>>> + struct arm_smmu_xen_domain *xen_domain = dom_iommu(d)->arch.priv; >>>>>> + >>>>>> + ASSERT(list_empty(&xen_domain->contexts)); >>>>>> + xfree(xen_domain); >>>>>> +} >>>>>> + >>>>>> +static int __must_check arm_smmu_map_page(struct domain *d, unsigned >>>>>> long gfn, >>>>>> + unsigned long mfn, unsigned int flags) >>>>>> +{ >>>>>> + p2m_type_t t; >>>>>> + >>>>>> + /* >>>>>> + * Grant mappings can be used for DMA requests. The dev_bus_addr >>>>>> + * returned by the hypercall is the MFN (not the IPA). For device >>> https://lists.xenproject.org/mailman/listinfo/xen-devel > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@xxxxxxxxxxxxxxxxxxxx > https://lists.xenproject.org/mailman/listinfo/xen-devel -- Qualcomm Datacenter Technologies as an affiliate of Qualcomm Technologies, Inc. Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |