From: Jan Beulich Date: Thu, 16 Nov 2017 09:37:29 +0000 (+0100) Subject: x86: don't wrongly trigger linear page table assertion X-Git-Tag: archive/raspbian/4.11.1-1+rpi1~1^2~66^2~1027 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=2c458dfcb59f3d9d8a35fc5ffbf780b6ed7a26a6;p=xen.git x86: don't wrongly trigger linear page table assertion _put_page_type() may do multiple iterations until its cmpxchg() succeeds. It invokes set_tlbflush_timestamp() on the first iteration, however. Code inside the function takes care of this, but - the assertion in _put_final_page_type() would trigger on the second iteration if time stamps in a debug build are permitted to be sufficiently much wider than the default 6 bits (see WRAP_MASK in flushtlb.c), - it returning -EINTR (for a continuation to be scheduled) would leave the page inconsistent state (until the re-invocation completes). Make the set_tlbflush_timestamp() invocation conditional, bypassing it (for now) only in the case we really can't tolerate the stamp to be stored. This is part of XSA-240. Signed-off-by: Jan Beulich Reviewed-by: George Dunlap --- diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 64ccd70ce3..886a5ee327 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2477,26 +2477,19 @@ static int _put_page_type(struct page_info *page, bool preemptible, break; } -#ifdef CONFIG_PV_LINEAR_PT - if ( ptpg && PGT_type_equal(x, ptpg->u.inuse.type_info) ) + if ( !ptpg || !PGT_type_equal(x, ptpg->u.inuse.type_info) ) { /* * set_tlbflush_timestamp() accesses the same union - * linear_pt_count lives in. Unvalidated page table pages, - * however, should occur during domain destruction only - * anyway. Updating of linear_pt_count luckily is not - * necessary anymore for a dying domain. + * linear_pt_count lives in. Pages (including page table ones), + * however, don't need their flush time stamp set except when + * the last reference is being dropped. For page table pages + * this happens in _put_final_page_type(). */ - ASSERT(page_get_owner(page)->is_dying); - ASSERT(page->linear_pt_count < 0); - ASSERT(ptpg->linear_pt_count > 0); - ptpg = NULL; + set_tlbflush_timestamp(page); } -#else /* CONFIG_PV_LINEAR_PT */ - BUG_ON(ptpg && PGT_type_equal(x, ptpg->u.inuse.type_info)); -#endif - - set_tlbflush_timestamp(page); + else + BUG_ON(!IS_ENABLED(CONFIG_PV_LINEAR_PT)); } else if ( unlikely((nx & (PGT_locked | PGT_count_mask)) == (PGT_locked | 1)) )