Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 09ed3d5b authored by Wei Liu's avatar Wei Liu Committed by David Vrabel
Browse files

xen/balloon: flush persistent kmaps in correct position



Xen balloon driver will update ballooned out pages' P2M entries to point
to scratch page for PV guests. In 24f69373 ("xen/balloon: don't alloc
page while non-preemptible", kmap_flush_unused was moved after updating
P2M table. In that case for 32 bit PV guest we might end up with

  P2M    X -----> S  (S is mfn of balloon scratch page)
  M2P    Y -----> X  (Y is mfn in persistent kmap entry)

kmap_flush_unused() iterates through all the PTEs in the kmap address
space, using pte_to_page() to obtain the page. If the p2m and the m2p
are inconsistent the incorrect page is returned.  This will clear
page->address on the wrong page which may cause subsequent oopses if
that page is currently kmap'ed.

Move the flush back between get_page and __set_phys_to_machine to fix
this.

Signed-off-by: default avatarWei Liu <wei.liu2@citrix.com>
Signed-off-by: default avatarDavid Vrabel <david.vrabel@citrix.com>
Cc: stable@vger.kernel.org # 3.12+
parent b098d672
Loading
Loading
Loading
Loading
+18 −6
Original line number Diff line number Diff line
@@ -399,11 +399,25 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
			state = BP_EAGAIN;
			break;
		}
		scrub_page(page);

		pfn = page_to_pfn(page);
		frame_list[i] = pfn_to_mfn(pfn);
		frame_list[i] = page_to_pfn(page);
	}

		scrub_page(page);
	/*
	 * Ensure that ballooned highmem pages don't have kmaps.
	 *
	 * Do this before changing the p2m as kmap_flush_unused()
	 * reads PTEs to obtain pages (and hence needs the original
	 * p2m entry).
	 */
	kmap_flush_unused();

	/* Update direct mapping, invalidate P2M, and add to balloon. */
	for (i = 0; i < nr_pages; i++) {
		pfn = frame_list[i];
		frame_list[i] = pfn_to_mfn(pfn);
		page = pfn_to_page(pfn);

#ifdef CONFIG_XEN_HAVE_PVMMU
		/*
@@ -429,11 +443,9 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
		}
#endif

		balloon_append(pfn_to_page(pfn));
		balloon_append(page);
	}

	/* Ensure that ballooned highmem pages don't have kmaps. */
	kmap_flush_unused();
	flush_tlb_all();

	set_xen_guest_handle(reservation.extent_start, frame_list);