On 05/10/17 14:08, John Garry wrote: > On 05/10/2017 13:44, Robin Murphy wrote: >> On 05/10/17 13:37, John Garry wrote: >>> On 05/10/2017 12:07, Robin Murphy wrote: >>>> On 04/10/17 14:50, Lorenzo Pieralisi wrote: >>>>> On Wed, Oct 04, 2017 at 12:22:04PM +0100, Marc Zyngier wrote: >>>>>> On 27/09/17 14:32, Shameer Kolothum wrote: >>>>>>> From: John Garry <john.garry@xxxxxxxxxx> >>>>>>> >>>>>>> On some platforms msi-controller address regions have to be excluded >>>>>>> from normal IOVA allocation in that they are detected and decoded in >>>>>>> a HW specific way by system components and so they cannot be >>>>>>> considered >>>>>>> normal IOVA address space. >>>>>>> >>>>>>> Add a helper function that retrieves msi address regions through >>>>>>> device >>>>>>> tree msi mapping, so that these regions will not be translated by >>>>>>> IOMMU >>>>>>> and will be excluded from IOVA allocations. >>>>>>> >>>>>>> Signed-off-by: John Garry <john.garry@xxxxxxxxxx> >>>>>>> [Shameer: Modified msi-parent retrieval logic] >>>>>>> Signed-off-by: Shameer Kolothum >>>>>>> <shameerali.kolothum.thodi@xxxxxxxxxx> >>>>>>> --- >>>>>>> drivers/iommu/of_iommu.c | 95 >>>>>>> ++++++++++++++++++++++++++++++++++++++++++++++++ >>>>>>> include/linux/of_iommu.h | 10 +++++ >>>>>>> 2 files changed, 105 insertions(+) >>>>>>> >>>>>>> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c >>>>>>> index e60e3db..ffd7fb7 100644 >>>>>>> --- a/drivers/iommu/of_iommu.c >>>>>>> +++ b/drivers/iommu/of_iommu.c >>>>>>> @@ -21,6 +21,7 @@ >>>>>>> #include <linux/iommu.h> >>>>>>> #include <linux/limits.h> >>>>>>> #include <linux/of.h> >>>>>>> +#include <linux/of_address.h> >>>>>>> #include <linux/of_iommu.h> >>>>>>> #include <linux/of_pci.h> >>>>>>> #include <linux/slab.h> >>>>>>> @@ -138,6 +139,14 @@ static int of_iommu_xlate(struct device *dev, >>>>>>> return ops->of_xlate(dev, iommu_spec); >>>>>>> } >>>>>>> >>>>>>> +static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void >>>>>>> *data) >>>>>>> +{ >>>>>>> + u32 *rid = data; >>>>>>> + >>>>>>> + *rid = alias; >>>>>>> + return 0; >>>>>>> +} >>>>>>> + >>>>>>> struct of_pci_iommu_alias_info { >>>>>>> struct device *dev; >>>>>>> struct device_node *np; >>>>>>> @@ -163,6 +172,73 @@ static int of_pci_iommu_init(struct pci_dev >>>>>>> *pdev, u16 alias, void *data) >>>>>>> return info->np == pdev->bus->dev.of_node; >>>>>>> } >>>>>>> >>>>>>> +static int of_iommu_alloc_resv_region(struct device_node *np, >>>>>>> + struct list_head *head) >>>>>>> +{ >>>>>>> + int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO; >>>>>>> + struct iommu_resv_region *region; >>>>>>> + struct resource res; >>>>>>> + int err; >>>>>>> + >>>>>>> + err = of_address_to_resource(np, 0, &res); >>>>>> >>>>>> What is the rational for registering the first region only? Surely >>>>>> you >>>>>> can have more than one region in an MSI controller (yes, your >>>>>> particular >>>>>> case is the ITS which has only one, but we're trying to do something >>>>>> generic here). >>>>>> >>>>>> Another issue I have with this code is that it inserts all of the ITS >>>>>> MMIO in the RESV_MSI range. As long as we don't generate any page >>>>>> tables >>>>>> for this, we're fine. But if we ever change this, we'll end-up >>>>>> with the >>>>>> ITS programming interface being exposed to a device, which >>>>>> wouldn't be >>>>>> acceptable. >>>>>> >>>>>> Why can't we have some generic property instead, that would describe >>>>>> the >>>>>> actual ranges that cannot be translated? That way, no random >>>>>> insertion >>>>>> of a random range, and relatively future proof. >>>> >>>> Indeed. Furthermore, IORT has the advantage of being limited to a few >>>> distinct device types and SBSA-compliant system topologies, so the >>>> ITS-chasing is reasonable there (modulo only reserving >>>> GITS_TRANSLATER). >>>> The scope of DT covers more embedded things as well like PCI host >>>> controllers with internal MSI doorbells, and potentially even >>>> direct-mapped memory regions for things like bootloader framebuffers to >>>> prevent display glitches - a generic address/size/flags description >>>> of a >>>> region could work for just about everything. >>>> >>>>> IORT code has the same issue (ie it reserves all ITS regions) and I do >>>>> not know where a property can be added to describe those ranges (IORT >>>>> specs ? I'd rather not) in ACPI other than the IORT tables entries >>>>> themselves. >>>>> >>>>>> I'm not sure where to declare it (PCIe node? IOMMU node?), but it'd >>>>>> feel >>>>>> like a much nicer and simpler solution to this problem. >>>>> >>>>> It could be but if we throw ACPI into the picture we have to knock >>>>> together Hisilicon specific namespace bindings to handle this and >>>>> quickly. >>>> >>>> As above I'm happy with the ITS-specific solution for ACPI given the >>>> limits of IORT. What I had in mind for DT was something tied in with >>>> the >>>> generic IOMMU bindings. Something like this is probably easiest to >>>> handle, but does rather spread the information around: >>>> >>>> >>>> pci { >>>> ... >>>> iommu-map = <0 0 &iommu1 0x10000>; >>>> iommu-reserved-ranges = <0x12340000 0x1000 IOMMU_MSI>, >>>> <0x34560000 0x1000 IOMMU_MSI>; >>>> }; >>>> >>>> display { >>>> ... >>>> iommus = <&iommu1 0x20000>; >>>> /* simplefb region */ >>>> iommu-reserved-ranges = <0x80080000 0x80000 IOMMU_DIRECT>, >>>> }; >>>> >>>> >>>> Alternatively, something inspired by reserved-memory might perhaps be >>>> conceptually neater, at the risk of being more complicated: >>>> >>>> >>>> iommu1: iommu@acbd0000 { >>>> ... >>>> #iommu-cells = <1>; >>>> >>>> iommu-reserved-ranges { >>>> #address-cells = <1>; >>>> #size-cells = <1>; >>>> >>>> its0_resv: msi@12340000 { >>>> compatible = "iommu-msi-region"; >>>> reg = <0x12340000 0x1000>; >>>> }; >>>> >>>> its1_resv: msi@34560000 { >>>> compatible = "iommu-msi-region"; >>>> reg = <0x34560000 0x1000>; >>>> }; >>>> >>>> fb_resv: direct@12340000 { >>>> compatible = "iommu-direct-region"; >>>> reg = <0x80080000 0x80000>; >>>> }; >>>> }; >>>> }; >>>> >>>> >>> >>> If we did this, wouldn't it be easier to create dangerous reserved >>> regions, like our ITS region which Marc was concerned by? It's not so >>> hard to get dts changes into the kernel. >> >> Well, yeah. It's also equally easy to add some peripheral register >> region to the /memory node and watch hilarity ensue. The solution to >> both is "don't put bogus crap in your DT". >> > > Sure, but people make mistakes and often a lot more subtle than your > example. I wanted to write a response to that but since it was too easy to hit the wrong keys on my keyboard, I didn't. I don't see a proposal for some alternate method of describing restricted IOVA regions which scales beyond HiSilicon Hip07 and would be entirely immune to bugs, so I'm really not sure what your argument is here :/ Robin. > Only one person spotted the problem with our approach to the ITS > problem. I'm pretty confident it would not have been spotted if it was > submitted as a dts change. > > Much appreciated, > John > >> There's a big difference between wilfully misdescribing your platform >> requirements vs. having the kernel automatically infer something but >> leave a hole open in the process. >> >> Robin. >> >> . >> > > -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html