diff --git a/xen/common/memory.c b/xen/common/memory.c index 9443e35a7f..4afa2271b7 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -233,8 +233,6 @@ static void populate_physmap(struct memop_args *a) unsigned int i, j; xen_pfn_t gpfn; struct domain *d = a->domain, *curr_d = current->domain; - bool need_tlbflush = false; - uint32_t tlbflush_timestamp = 0; if ( !guest_handle_subrange_okay(a->extent_list, a->nr_done, a->nr_extents-1) ) @@ -246,15 +244,6 @@ static void populate_physmap(struct memop_args *a) if ( unlikely(!d->creation_finished) ) { - /* - * With MEMF_no_tlbflush set, alloc_heap_pages() will ignore - * TLB-flushes. After VM creation, this is a security issue (it can - * make pages accessible to guest B, when guest A may still have a - * cached mapping to them). So we do this only during domain creation, - * when the domain itself has not yet been unpaused for the first - * time. - */ - a->memflags |= MEMF_no_tlbflush; /* * With MEMF_no_icache_flush, alloc_heap_pages() will skip * performing icache flushes. We do it only before domain @@ -397,13 +386,6 @@ static void populate_physmap(struct memop_args *a) } } - if ( unlikely(a->memflags & MEMF_no_tlbflush) ) - { - for ( j = 0; j < (1U << a->extent_order); j++ ) - accumulate_tlbflush(&need_tlbflush, &page[j], - &tlbflush_timestamp); - } - mfn = page_to_mfn(page); } @@ -418,9 +400,6 @@ static void populate_physmap(struct memop_args *a) } out: - if ( need_tlbflush ) - filtered_flush_tlb_mask(tlbflush_timestamp); - if ( a->memflags & MEMF_no_icache_flush ) invalidate_icache(); diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index 1e47f38721..62ac89b824 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -1101,15 +1101,17 @@ static struct page_info *alloc_heap_pages( /* Preserve PGC_need_scrub so we can check it after lock is dropped. */ pg[i].count_info = PGC_state_inuse | (pg[i].count_info & PGC_need_scrub); - if ( !(memflags & MEMF_no_tlbflush) ) - accumulate_tlbflush(&need_tlbflush, &pg[i], - &tlbflush_timestamp); + accumulate_tlbflush(&need_tlbflush, &pg[i], &tlbflush_timestamp); init_free_page_fields(&pg[i]); } spin_unlock(&heap_lock); + /* Flush ahead of scrubbing: ensure no PV domain has a stale TLB entry. */ + if ( need_tlbflush ) + filtered_flush_tlb_mask(tlbflush_timestamp); + if ( first_dirty != INVALID_DIRTY_IDX || (scrub_debug && !(memflags & MEMF_no_scrub)) ) { @@ -1145,9 +1147,6 @@ static struct page_info *alloc_heap_pages( } } - if ( need_tlbflush ) - filtered_flush_tlb_mask(tlbflush_timestamp); - /* * Ensure cache and RAM are consistent for platforms where the guest * can control its own visibility of/through the cache. @@ -1409,6 +1408,13 @@ bool scrub_free_pages(void) { if ( test_bit(_PGC_need_scrub, &pg[i].count_info) ) { + bool need_tlbflush = false; + uint32_t tlbflush_ts = 0; + + accumulate_tlbflush(&need_tlbflush, &pg[i], &tlbflush_ts); + if ( need_tlbflush ) + filtered_flush_tlb_mask(tlbflush_ts); + scrub_one_page(&pg[i], true); /* * We can modify count_info without holding heap @@ -2077,7 +2083,7 @@ static struct page_info *alloc_color_heap_page(unsigned int memflags, uint32_t tlbflush_timestamp = 0; bool need_scrub; - if ( memflags & ~(MEMF_no_refcount | MEMF_no_owner | MEMF_no_tlbflush | + if ( memflags & ~(MEMF_no_refcount | MEMF_no_owner | MEMF_no_icache_flush | MEMF_no_scrub) ) return NULL; @@ -2106,13 +2112,16 @@ static struct page_info *alloc_color_heap_page(unsigned int memflags, free_colored_pages[color]--; page_list_del(pg, color_heap(color)); - if ( !(memflags & MEMF_no_tlbflush) ) - accumulate_tlbflush(&need_tlbflush, pg, &tlbflush_timestamp); + accumulate_tlbflush(&need_tlbflush, pg, &tlbflush_timestamp); init_free_page_fields(pg); spin_unlock(&heap_lock); + /* Flush ahead of scrubbing: ensure no PV domain has a stale TLB entry. */ + if ( need_tlbflush ) + filtered_flush_tlb_mask(tlbflush_timestamp); + if ( !(memflags & MEMF_no_scrub) ) { if ( need_scrub ) @@ -2121,9 +2130,6 @@ static struct page_info *alloc_color_heap_page(unsigned int memflags, check_one_page(pg); } - if ( need_tlbflush ) - filtered_flush_tlb_mask(tlbflush_timestamp); - flush_page_to_ram(mfn_x(page_to_mfn(pg)), !(memflags & MEMF_no_icache_flush)); @@ -3041,9 +3047,7 @@ static bool prepare_staticmem_pages(struct page_info *pg, unsigned long nr_mfns, goto out_err; } - if ( !(memflags & MEMF_no_tlbflush) ) - accumulate_tlbflush(&need_tlbflush, &pg[i], - &tlbflush_timestamp); + accumulate_tlbflush(&need_tlbflush, &pg[i], &tlbflush_timestamp); /* * Preserve flag PGC_static and change page state diff --git a/xen/include/xen/mm.h b/xen/include/xen/mm.h index fd8b0ba3f5..153c57f5dd 100644 --- a/xen/include/xen/mm.h +++ b/xen/include/xen/mm.h @@ -222,8 +222,6 @@ struct npfec { #define MEMF_exact_node (1U<<_MEMF_exact_node) #define _MEMF_no_owner 5 #define MEMF_no_owner (1U<<_MEMF_no_owner) -#define _MEMF_no_tlbflush 6 -#define MEMF_no_tlbflush (1U<<_MEMF_no_tlbflush) #define _MEMF_no_icache_flush 7 #define MEMF_no_icache_flush (1U<<_MEMF_no_icache_flush) #define _MEMF_no_scrub 8