|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 4/4] x86/mm: Remove force-invalidate loop
The comment about the "force-invalidate" loop gives two reasons for
its existence:
1. Breaking circular "linear pagetable" references
2. Cleaning up partially-validated pages.
The first reason been invalid since XSA-240: Since then it hasn't been
possible to generate circular linear pagetable references.
The second reason has been invalid since long before that: Before
calling relinquish_memory(), domain_relinquish_resources() calls
vcpu_destroy_pagetables() on each vcpu; this will in turn call
put_old_guest_table() on each vcpu. The result should be that it's
not possible to have top-level partially-devalidated pagetables by the
time we get to relinquish_memory().
The loop, it turns out, was effectively there only to pick up
interrupted UNPIN operations of relinquish_memory() itself. Now that
these are being handled by put_old_guest_table(), we can remove this
loop entirely.
Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxx>
---
This patch has the advantage that it doesn't hide mis-accounted
partial pages anymore; but has the disadvantage that if there *is*
such a mis-accounting, it will become a resource leak (and thus an
XSA). It might be a good idea to add another "clean up partial pages"
pass after all other pages have been cleaned up, with a suitable
ASSERT(). That way we have a higher chance of catching mis-accounting
during development, without risking opening up a memory / domain leak
in production.
CC: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CC: Jan Beulich <jbeulich@xxxxxxxx>
---
xen/arch/x86/domain.c | 71 -------------------------------------------
1 file changed, 71 deletions(-)
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index b7968463cb..847a70302c 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -1950,7 +1950,6 @@ static int relinquish_memory(
struct domain *d, struct page_list_head *list, unsigned long type)
{
struct page_info *page;
- unsigned long x, y;
int ret = 0;
ret = put_old_guest_table(current);
@@ -2004,76 +2003,6 @@ static int relinquish_memory(
put_page_alloc_ref(page);
- /*
- * Forcibly invalidate top-most, still valid page tables at this point
- * to break circular 'linear page table' references as well as clean up
- * partially validated pages. This is okay because MMU structures are
- * not shared across domains and this domain is now dead. Thus top-most
- * valid tables are not in use so a non-zero count means circular
- * reference or partially validated.
- */
- y = page->u.inuse.type_info;
- for ( ; ; )
- {
- x = y;
- if ( likely((x & PGT_type_mask) != type) ||
- likely(!(x & (PGT_validated|PGT_partial))) )
- break;
-
- y = cmpxchg(&page->u.inuse.type_info, x,
- x & ~(PGT_validated|PGT_partial));
- if ( likely(y == x) )
- {
- /* No need for atomic update of type_info here: noone else
updates it. */
- switch ( ret = devalidate_page(page, x, 1) )
- {
- case 0:
- break;
- case -EINTR:
- page_list_add(page, list);
- page->u.inuse.type_info |= PGT_validated;
- if ( x & PGT_partial )
- put_page(page);
- put_page(page);
- ret = -ERESTART;
- goto out;
- case -ERESTART:
- page_list_add(page, list);
- /*
- * PGT_partial holds a type ref and a general ref.
- * If we came in with PGT_partial set, then we 1)
- * don't need to grab an extra type count, and 2)
- * do need to drop the extra page ref we grabbed
- * at the top of the loop. If we didn't come in
- * with PGT_partial set, we 1) do need to drab an
- * extra type count, but 2) can transfer the page
- * ref we grabbed above to it.
- *
- * Note that we must increment type_info before
- * setting PGT_partial. Theoretically it should
- * be safe to drop the page ref before setting
- * PGT_partial, but do it afterwards just to be
- * extra safe.
- */
- if ( !(x & PGT_partial) )
- page->u.inuse.type_info++;
- smp_wmb();
- page->u.inuse.type_info |= PGT_partial;
- if ( x & PGT_partial )
- put_page(page);
- goto out;
- default:
- BUG();
- }
- if ( x & PGT_partial )
- {
- page->u.inuse.type_info--;
- put_page(page);
- }
- break;
- }
- }
-
/* Put the page on the list and /then/ potentially free it. */
page_list_add_tail(page, &d->arch.relmem_list);
put_page(page);
--
2.24.0
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |