Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Jun 2014 09:51:08 +0000 (UTC)
From:      Roger Pau Monné <royger@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r267858 - in head/sys/dev: virtio/balloon xen/balloon
Message-ID:  <201406250951.s5P9p8YR017159@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: royger
Date: Wed Jun 25 09:51:08 2014
New Revision: 267858
URL: http://svnweb.freebsd.org/changeset/base/267858

Log:
  xen/virtio: fix balloon drivers to not mark pages as WIRED
  
  Prevent the Xen and VirtIO balloon drivers from marking pages as
  wired. This prevents them from increasing the system wired page count,
  which can lead to mlock failing because of hitting the limit in
  vm.max_wired.
  
  In the Xen case make sure pages are zeroed before giving them back to
  the hypervisor, or else we might be leaking data. Also remove the
  balloon_{append/retrieve} and link pages directly into the
  ballooned_pages queue using the plinks.q field in the page struct.
  
  Sponsored by: Citrix Systems R&D
  Reviewed by: kib, bryanv
  Approved by: gibbs
  
  dev/virtio/balloon/virtio_balloon.c:
   - Don't allocate pages with VM_ALLOC_WIRED.
  
  dev/xen/balloon/balloon.c:
   - Don't allocate pages with VM_ALLOC_WIRED.
   - Make sure pages are zeroed before giving them back to the
     hypervisor.
   - Remove the balloon_entry struct and the balloon_{append/retrieve}
     functions and use the page plinks.q entry to link the pages
     directly into the ballooned_pages queue.

Modified:
  head/sys/dev/virtio/balloon/virtio_balloon.c
  head/sys/dev/xen/balloon/balloon.c

Modified: head/sys/dev/virtio/balloon/virtio_balloon.c
==============================================================================
--- head/sys/dev/virtio/balloon/virtio_balloon.c	Wed Jun 25 08:55:20 2014	(r267857)
+++ head/sys/dev/virtio/balloon/virtio_balloon.c	Wed Jun 25 09:51:08 2014	(r267858)
@@ -438,8 +438,7 @@ vtballoon_alloc_page(struct vtballoon_so
 {
 	vm_page_t m;
 
-	m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | VM_ALLOC_WIRED |
-	    VM_ALLOC_NOOBJ);
+	m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ);
 	if (m != NULL)
 		sc->vtballoon_current_npages++;
 
@@ -450,7 +449,6 @@ static void
 vtballoon_free_page(struct vtballoon_softc *sc, vm_page_t m)
 {
 
-	vm_page_unwire(m, PQ_INACTIVE);
 	vm_page_free(m);
 	sc->vtballoon_current_npages--;
 }

Modified: head/sys/dev/xen/balloon/balloon.c
==============================================================================
--- head/sys/dev/xen/balloon/balloon.c	Wed Jun 25 08:55:20 2014	(r267857)
+++ head/sys/dev/xen/balloon/balloon.c	Wed Jun 25 09:51:08 2014	(r267858)
@@ -94,13 +94,8 @@ SYSCTL_ULONG(_dev_xen_balloon, OID_AUTO,
 SYSCTL_ULONG(_dev_xen_balloon, OID_AUTO, high_mem, CTLFLAG_RD,
     &bs.balloon_high, 0, "High-mem balloon");
 
-struct balloon_entry {
-	vm_page_t page;
-	STAILQ_ENTRY(balloon_entry) list;
-};
-
 /* List of ballooned pages, threaded through the mem_map array. */
-static STAILQ_HEAD(,balloon_entry) ballooned_pages;
+static TAILQ_HEAD(,vm_page) ballooned_pages;
 
 /* Main work function, always executed in process context. */
 static void balloon_process(void *unused);
@@ -110,47 +105,6 @@ static void balloon_process(void *unused
 #define WPRINTK(fmt, args...) \
 	printk(KERN_WARNING "xen_mem: " fmt, ##args)
 
-/* balloon_append: add the given page to the balloon. */
-static int
-balloon_append(vm_page_t page)
-{
-	struct balloon_entry *entry;
-
-	mtx_assert(&balloon_mutex, MA_OWNED);
-
-	entry = malloc(sizeof(struct balloon_entry), M_BALLOON, M_NOWAIT);
-	if (!entry)
-		return (ENOMEM);
-	entry->page = page;
-	STAILQ_INSERT_HEAD(&ballooned_pages, entry, list);
-	bs.balloon_low++;
-
-	return (0);
-}
-
-/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
-static vm_page_t
-balloon_retrieve(void)
-{
-	vm_page_t page;
-	struct balloon_entry *entry;
-
-	mtx_assert(&balloon_mutex, MA_OWNED);
-
-	if (STAILQ_EMPTY(&ballooned_pages))
-		return (NULL);
-
-	entry = STAILQ_FIRST(&ballooned_pages);
-	STAILQ_REMOVE_HEAD(&ballooned_pages, list);
-
-	page = entry->page;
-	free(entry, M_BALLOON);
-	
-	bs.balloon_low--;
-
-	return (page);
-}
-
 static unsigned long 
 current_target(void)
 {
@@ -203,7 +157,6 @@ static int 
 increase_reservation(unsigned long nr_pages)
 {
 	unsigned long  pfn, i;
-	struct balloon_entry *entry;
 	vm_page_t      page;
 	long           rc;
 	struct xen_memory_reservation reservation = {
@@ -217,10 +170,9 @@ increase_reservation(unsigned long nr_pa
 	if (nr_pages > nitems(frame_list))
 		nr_pages = nitems(frame_list);
 
-	for (entry = STAILQ_FIRST(&ballooned_pages), i = 0;
-	     i < nr_pages; i++, entry = STAILQ_NEXT(entry, list)) {
-		KASSERT(entry, ("ballooned_pages list corrupt"));
-		page = entry->page;
+	for (page = TAILQ_FIRST(&ballooned_pages), i = 0;
+	    i < nr_pages; i++, page = TAILQ_NEXT(page, plinks.q)) {
+		KASSERT(page != NULL, ("ballooned_pages list corrupt"));
 		frame_list[i] = (VM_PAGE_TO_PHYS(page) >> PAGE_SHIFT);
 	}
 
@@ -245,8 +197,10 @@ increase_reservation(unsigned long nr_pa
 	}
 
 	for (i = 0; i < nr_pages; i++) {
-		page = balloon_retrieve();
-		KASSERT(page, ("balloon_retrieve failed"));
+		page = TAILQ_FIRST(&ballooned_pages);
+		KASSERT(page != NULL, ("Unable to get ballooned page"));
+		TAILQ_REMOVE(&ballooned_pages, page, plinks.q);
+		bs.balloon_low--;
 
 		pfn = (VM_PAGE_TO_PHYS(page) >> PAGE_SHIFT);
 		KASSERT((xen_feature(XENFEAT_auto_translated_physmap) ||
@@ -255,7 +209,6 @@ increase_reservation(unsigned long nr_pa
 
 		set_phys_to_machine(pfn, frame_list[i]);
 
-		vm_page_unwire(page, PQ_INACTIVE);
 		vm_page_free(page);
 	}
 
@@ -286,24 +239,29 @@ decrease_reservation(unsigned long nr_pa
 	for (i = 0; i < nr_pages; i++) {
 		if ((page = vm_page_alloc(NULL, 0, 
 			    VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ | 
-			    VM_ALLOC_WIRED | VM_ALLOC_ZERO)) == NULL) {
+			    VM_ALLOC_ZERO)) == NULL) {
 			nr_pages = i;
 			need_sleep = 1;
 			break;
 		}
 
+		if ((page->flags & PG_ZERO) == 0) {
+			/*
+			 * Zero the page, or else we might be leaking
+			 * important data to other domains on the same
+			 * host. Xen doesn't scrub ballooned out memory
+			 * pages, the guest is in charge of making
+			 * sure that no information is leaked.
+			 */
+			pmap_zero_page(page);
+		}
+
 		pfn = (VM_PAGE_TO_PHYS(page) >> PAGE_SHIFT);
 		frame_list[i] = PFNTOMFN(pfn);
 
 		set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
-		if (balloon_append(page) != 0) {
-			vm_page_unwire(page, PQ_INACTIVE);
-			vm_page_free(page);
-
-			nr_pages = i;
-			need_sleep = 1;
-			break;
-		}
+		TAILQ_INSERT_HEAD(&ballooned_pages, page, plinks.q);
+		bs.balloon_low++;
 	}
 
 	set_xen_guest_handle(reservation.extent_start, frame_list);
@@ -438,7 +396,8 @@ balloon_init(void *arg)
 	/* Initialise the balloon with excess memory space. */
 	for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
 		page = PHYS_TO_VM_PAGE(pfn << PAGE_SHIFT);
-		balloon_append(page);
+		TAILQ_INSERT_HEAD(&ballooned_pages, page, plinks.q);
+		bs.balloon_low++;
 	}
 #undef max_pfn
 #endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406250951.s5P9p8YR017159>