* [PATCH v2] IOMMU/x86: make page type checks consistent when mapping pages
@ 2019-05-14 12:11 ` Jan Beulich
0 siblings, 0 replies; 2+ messages in thread
From: Jan Beulich @ 2019-05-14 12:11 UTC (permalink / raw)
To: xen-devel; +Cc: George Dunlap, Andrew Cooper
There are currently three more or less different checks:
- _get_page_type() adjusts the IOMMU mappings according to the new type
alone,
- arch_iommu_populate_page_table() wants just the type to be
PGT_writable_page,
- iommu_hwdom_init() additionally permits all other types with a type
refcount of zero.
The canonical one is in _get_page_type(), and as of XSA-288
arch_iommu_populate_page_table() also has no need anymore to deal with
PGT_none pages. In the PV Dom0 case, however, PGT_none pages are still
necessary to consider, since in that case pages don't get handed to
guest_physmap_add_entry(). Furthermore, the function so far also
established r/o mappings, which is not in line with the rules set forth
by the XSA-288 change.
For arch_iommu_populate_page_table() to not encounter PGT_none pages
anymore even in cases where the IOMMU gets enabled for a domain only
when it is already running, replace the IOMMU dependency in
guest_physmap_add_entry()'s handling of PV guests to check just the
system wide state instead of the domain property.
Unfortunately (partially) replacing the iommu_map() call in
iommu_hwdom_init() implies resurrecting the flush suppression that got
previously eliminated. Note that the call to iommu_map() can't be
removed at this point in time - Dom0's initial allocation gets its page
types set before iommu_hwdom_init() runs.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v2: Fix IOTLB flushing. Exclude PVH. Use type safe local variables.
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -873,11 +873,11 @@ guest_physmap_add_entry(struct domain *d
*
* Retain this property by grabbing a writable type ref and then
* dropping it immediately. The result will be pages that have a
- * writable type (and an IOMMU entry), but a count of 0 (such that
- * any guest-requested type changes succeed and remove the IOMMU
- * entry).
+ * writable type (and an IOMMU entry if necessary), but a count of 0
+ * (such that any guest-requested type changes succeed and remove the
+ * IOMMU entry).
*/
- if ( !need_iommu_pt_sync(d) || t != p2m_ram_rw )
+ if ( !iommu_enabled || t != p2m_ram_rw )
return 0;
for ( i = 0; i < (1UL << page_order); ++i, ++page )
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -192,28 +192,46 @@ void __hwdom_init iommu_hwdom_init(struc
unsigned int i = 0, flush_flags = 0;
int rc = 0;
+ this_cpu(iommu_dont_flush_iotlb) = true;
+
page_list_for_each ( page, &d->page_list )
{
- unsigned long mfn = mfn_x(page_to_mfn(page));
- unsigned long dfn = mfn_to_gmfn(d, mfn);
- unsigned int mapping = IOMMUF_readable;
- int ret;
-
- if ( ((page->u.inuse.type_info & PGT_count_mask) == 0) ||
- ((page->u.inuse.type_info & PGT_type_mask)
- == PGT_writable_page) )
- mapping |= IOMMUF_writable;
-
- ret = iommu_map(d, _dfn(dfn), _mfn(mfn), 0, mapping,
- &flush_flags);
-
- if ( !rc )
- rc = ret;
+ switch ( page->u.inuse.type_info & PGT_type_mask )
+ {
+ case PGT_none:
+ if ( is_pv_domain(d) )
+ {
+ ASSERT(!(page->u.inuse.type_info & PGT_count_mask));
+ if ( get_page_and_type(page, d, PGT_writable_page) )
+ {
+ put_page_and_type(page);
+ flush_flags |= IOMMUF_readable | IOMMUF_writable;
+ }
+ else if ( !rc )
+ rc = -EBUSY;
+ break;
+ }
+ /* fall through */
+ case PGT_writable_page:
+ {
+ mfn_t mfn = page_to_mfn(page);
+ dfn_t dfn = _dfn(mfn_to_gmfn(d, mfn_x(mfn)));
+ int ret = iommu_map(d, dfn, mfn, 0,
+ IOMMUF_readable | IOMMUF_writable,
+ &flush_flags);
+
+ if ( !rc )
+ rc = ret;
+ break;
+ }
+ }
if ( !(i++ & 0xfffff) )
process_pending_softirqs();
}
+ this_cpu(iommu_dont_flush_iotlb) = false;
+
/* Use while-break to avoid compiler warning */
while ( iommu_iotlb_flush_all(d, flush_flags) )
break;
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply [flat|nested] 2+ messages in thread
* [Xen-devel] [PATCH v2] IOMMU/x86: make page type checks consistent when mapping pages
@ 2019-05-14 12:11 ` Jan Beulich
0 siblings, 0 replies; 2+ messages in thread
From: Jan Beulich @ 2019-05-14 12:11 UTC (permalink / raw)
To: xen-devel; +Cc: George Dunlap, Andrew Cooper
There are currently three more or less different checks:
- _get_page_type() adjusts the IOMMU mappings according to the new type
alone,
- arch_iommu_populate_page_table() wants just the type to be
PGT_writable_page,
- iommu_hwdom_init() additionally permits all other types with a type
refcount of zero.
The canonical one is in _get_page_type(), and as of XSA-288
arch_iommu_populate_page_table() also has no need anymore to deal with
PGT_none pages. In the PV Dom0 case, however, PGT_none pages are still
necessary to consider, since in that case pages don't get handed to
guest_physmap_add_entry(). Furthermore, the function so far also
established r/o mappings, which is not in line with the rules set forth
by the XSA-288 change.
For arch_iommu_populate_page_table() to not encounter PGT_none pages
anymore even in cases where the IOMMU gets enabled for a domain only
when it is already running, replace the IOMMU dependency in
guest_physmap_add_entry()'s handling of PV guests to check just the
system wide state instead of the domain property.
Unfortunately (partially) replacing the iommu_map() call in
iommu_hwdom_init() implies resurrecting the flush suppression that got
previously eliminated. Note that the call to iommu_map() can't be
removed at this point in time - Dom0's initial allocation gets its page
types set before iommu_hwdom_init() runs.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v2: Fix IOTLB flushing. Exclude PVH. Use type safe local variables.
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -873,11 +873,11 @@ guest_physmap_add_entry(struct domain *d
*
* Retain this property by grabbing a writable type ref and then
* dropping it immediately. The result will be pages that have a
- * writable type (and an IOMMU entry), but a count of 0 (such that
- * any guest-requested type changes succeed and remove the IOMMU
- * entry).
+ * writable type (and an IOMMU entry if necessary), but a count of 0
+ * (such that any guest-requested type changes succeed and remove the
+ * IOMMU entry).
*/
- if ( !need_iommu_pt_sync(d) || t != p2m_ram_rw )
+ if ( !iommu_enabled || t != p2m_ram_rw )
return 0;
for ( i = 0; i < (1UL << page_order); ++i, ++page )
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -192,28 +192,46 @@ void __hwdom_init iommu_hwdom_init(struc
unsigned int i = 0, flush_flags = 0;
int rc = 0;
+ this_cpu(iommu_dont_flush_iotlb) = true;
+
page_list_for_each ( page, &d->page_list )
{
- unsigned long mfn = mfn_x(page_to_mfn(page));
- unsigned long dfn = mfn_to_gmfn(d, mfn);
- unsigned int mapping = IOMMUF_readable;
- int ret;
-
- if ( ((page->u.inuse.type_info & PGT_count_mask) == 0) ||
- ((page->u.inuse.type_info & PGT_type_mask)
- == PGT_writable_page) )
- mapping |= IOMMUF_writable;
-
- ret = iommu_map(d, _dfn(dfn), _mfn(mfn), 0, mapping,
- &flush_flags);
-
- if ( !rc )
- rc = ret;
+ switch ( page->u.inuse.type_info & PGT_type_mask )
+ {
+ case PGT_none:
+ if ( is_pv_domain(d) )
+ {
+ ASSERT(!(page->u.inuse.type_info & PGT_count_mask));
+ if ( get_page_and_type(page, d, PGT_writable_page) )
+ {
+ put_page_and_type(page);
+ flush_flags |= IOMMUF_readable | IOMMUF_writable;
+ }
+ else if ( !rc )
+ rc = -EBUSY;
+ break;
+ }
+ /* fall through */
+ case PGT_writable_page:
+ {
+ mfn_t mfn = page_to_mfn(page);
+ dfn_t dfn = _dfn(mfn_to_gmfn(d, mfn_x(mfn)));
+ int ret = iommu_map(d, dfn, mfn, 0,
+ IOMMUF_readable | IOMMUF_writable,
+ &flush_flags);
+
+ if ( !rc )
+ rc = ret;
+ break;
+ }
+ }
if ( !(i++ & 0xfffff) )
process_pending_softirqs();
}
+ this_cpu(iommu_dont_flush_iotlb) = false;
+
/* Use while-break to avoid compiler warning */
while ( iommu_iotlb_flush_all(d, flush_flags) )
break;
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2019-05-14 12:11 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-14 12:11 [PATCH v2] IOMMU/x86: make page type checks consistent when mapping pages Jan Beulich
2019-05-14 12:11 ` [Xen-devel] " Jan Beulich
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.