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

Re: [Xen-devel] [RFC PATCH 4/9] xen/arm: p2m: Update IOMMU mapping whenever possible if page table is not shared



On Fri, Apr 21, 2017 at 7:27 PM, Julien Grall <julien.grall@xxxxxxx> wrote:
>
>
> On 21/04/17 15:18, Oleksandr Tyshchenko wrote:
>>
>> On Wed, Apr 19, 2017 at 8:46 PM, Julien Grall <julien.grall@xxxxxxx>
>> wrote:
>>>
>>> Hi Oleksandr,
>>
>> Hi, Julien
>
>
> Hi Oleksandr,
Hi, Julien

>
>
>>>
>>> On 15/03/17 20:05, Oleksandr Tyshchenko wrote:
>>>>
>>>>
>>>> From: Oleksandr Tyshchenko <oleksandr_tyshchenko@xxxxxxxx>
>>>>
>>>> Update IOMMU mapping if the IOMMU doesn't share page table with the CPU.
>>>> The best place to do so on ARM is p2m_set_entry(). Use mfn as an
>>>> indicator
>>>> of the required action. If mfn is valid call iommu_map_pages(),
>>>> otherwise - iommu_unmap_pages().
>>>
>>>
>>>
>>> Can you explain in the commit message why you do this change in
>>> p2m_set_entry and not __p2m_set_entry?
>>
>> ok
>>
>>>
>>>
>>>>
>>>> Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@xxxxxxxx>
>>>> ---
>>>>  xen/arch/arm/p2m.c | 40 +++++++++++++++++++++++++++++++++++++++-
>>>>  1 file changed, 39 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>>>> index 1fc6ca3..84d3a09 100644
>>>> --- a/xen/arch/arm/p2m.c
>>>> +++ b/xen/arch/arm/p2m.c
>>>> @@ -979,7 +979,8 @@ static int __p2m_set_entry(struct p2m_domain *p2m,
>>>>      if ( p2m_valid(orig_pte) && entry->p2m.base != orig_pte.p2m.base )
>>>>          p2m_free_entry(p2m, orig_pte, level);
>>>>
>>>> -    if ( need_iommu(p2m->domain) && (p2m_valid(orig_pte) ||
>>>> p2m_valid(*entry)) )
>>>> +    if ( need_iommu(p2m->domain) && iommu_use_hap_pt(d) &&
>>>> +         (p2m_valid(orig_pte) || p2m_valid(*entry)) )
>>>>          rc = iommu_iotlb_flush(p2m->domain, gfn_x(sgfn), 1UL <<
>>>> page_order);
>>>>      else
>>>>          rc = 0;
>>>> @@ -997,6 +998,9 @@ int p2m_set_entry(struct p2m_domain *p2m,
>>>>                    p2m_type_t t,
>>>>                    p2m_access_t a)
>>>>  {
>>>> +    unsigned long orig_nr = nr;
>>>> +    gfn_t orig_sgfn = sgfn;
>>>> +    mfn_t orig_smfn = smfn;
>>>>      int rc = 0;
>>>>
>>>>      while ( nr )
>>>> @@ -1029,6 +1033,40 @@ int p2m_set_entry(struct p2m_domain *p2m,
>>>>          nr -= (1 << order);
>>>>      }
>>>>
>>>> +    if ( likely(!rc) )
>>>
>>>
>>>
>>> I would do
>>>
>>> if ( unlikely(rc) )
>>>   return rc;
>>>
>>> /* IOMMU map/unmap ... */
>>>
>>> This would remove one indentation layer of if.
>>
>> Agree.
>>
>>>
>>>> +    {
>>>> +        /*
>>>> +         * It's time to update IOMMU mapping if the latter doesn't
>>>> +         * share page table with the CPU. Pass the whole memory block
>>>> to
>>>> let
>>>> +         * the IOMMU code decide what to do with it.
>>>> +         * The reason to update IOMMU mapping outside "while loop" is
>>>> that
>>>> +         * the IOMMU might not support the pages/superpages the CPU can
>>>> deal
>>>> +         * with (4K, 2M, 1G) and as result this will lead to
>>>> non-optimal
>>>> +         * mapping.
>>>
>>>
>>>
>>> My worry with this solution is someone may decide to use __p2m_set_entry
>>> (see relinquish) directly because he knows the correct order. So the
>>> IOMMU
>>> would be correctly handled when page table are shared and not when they
>>> are
>>> "unshared".
>>
>> As for relinquish_p2m_mapping(), I was thinking about it, but I
>> decided not to remove IOMMU mapping here since
>> the whole IOMMU page table would be removed during
>> complete_domain_destroy().
>> But, I agree that nothing prevent someone to use __p2m_set_entry
>> directly in future.
>>
>>>
>>> I would probably extend __p2m_get_entry with a new parameter indication
>>> whether we want to map the page in the IOMMU directly or not.
>>
>> Sorry, I didn't get your point here. Did you mean __p2m_set_entry?
>
>
> Yes sorry.
>
>>
>>>
>>> Also, do you expect the IOMMU to support a page granularity bigger than
>>> the
>>> one supported by Xen? If not, we should probably have a check somewhere,
>>> to
>>> prevent potential security issue as we would map more than expected.
>>
>> At the moment I keep in mind IPMMU only. And it supports the same page
>> granularity as the CPU
>> (4K, 2M, 1G). Could you, please, explain what a proposed check should
>> check?
>
>
> We should check that the smallest granularity supported by the IOMMU is
> inferior or equal to PAGE_SIZE. If not, then there will be more rework
> required in Xen to support correctly those IOMMUs.
>
> For instance, Xen PAGE_SIZE is currently 4KB. If the IOMMUs only support
> 64KB, then you will end up to map a bigger chunk than expected leading a
> guest device to access memory it should not access.
>
> Supporting such IOMMU will require much more work in Xen than this small
> changes.

Aha. Seems, I understand what you meant. I already have a check in IPMMU driver:

/*
* both the virtual address and the physical one, as well as
* the size of the mapping, must be aligned (at least) to the
* size of the smallest page supported by the hardware
*/
if (!IS_ALIGNED(iova | paddr | size, min_pagesz)) {
printk("unaligned: iova 0x%lx pa 0x%"PRIx64" size 0x%zx min_pagesz 0x%x\n",
      iova, paddr, size, min_pagesz);
return -EINVAL;
}

where min_pagesz - is a minimum page size supported by hardware.
Hope, that this check can catch such case.

>
>
>> With the current solution we pass the whole memory block to the IOMMU
>> code and the IOMMU driver should handle this properly.
>> If we pass, for example 1,1 GB, but the IOMMU driver supports 4K pages
>> only then it has to split the memory block into 4K pages and process
>> them.
>
>
> The IOMMU driver will likely duplicate the same logic as in p2m_set_entry
> and today does not seem to be necessary. By that I mean splitting into
> smaller chunk.
>
> You may need to split again those chunks if the IOMMU does not support the
> granularity. But this is less likely on current hardware.
>
> My main concern is to make sure __p2m_get_entry works as expected with all
> the configurations. Currently, what you describe will require much more work
> than this series. I will be ok whether you rework __p2m_get_entry or not.
As we have already found common ground:
I will rework the patch by adding updating IOMMU mapping to
__p2m_set_entry and add new argument to it to
to show whether we have to update IOMMU mapping or not.
So, if we call  __p2m_set_entry directly, we have to force it to
update IOMMU mapping.

>
> Cheers,
>
> --
> Julien Grall



-- 
Regards,

Oleksandr Tyshchenko

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.