[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 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,


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.


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.

Cheers,

--
Julien Grall

_______________________________________________
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®.