summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroyger <royger@FreeBSD.org>2015-12-30 08:15:43 +0000
committerroyger <royger@FreeBSD.org>2015-12-30 08:15:43 +0000
commita3b7fafab78043fe8355bb68596028cb9bba40ad (patch)
tree8e7fc7e0be53dc52bea63d3c8e12b4849c1bfae9
parentc48693418e100bebee76155f54e84a1e171e34e8 (diff)
downloadFreeBSD-src-a3b7fafab78043fe8355bb68596028cb9bba40ad.zip
FreeBSD-src-a3b7fafab78043fe8355bb68596028cb9bba40ad.tar.gz
MFC r267858:
xen/virtio: fix balloon drivers to not mark pages as 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 Requested by: bapt
-rw-r--r--sys/dev/virtio/balloon/virtio_balloon.c4
-rw-r--r--sys/dev/xen/balloon/balloon.c89
2 files changed, 25 insertions, 68 deletions
diff --git a/sys/dev/virtio/balloon/virtio_balloon.c b/sys/dev/virtio/balloon/virtio_balloon.c
index a90a653..6d00ef3 100644
--- a/sys/dev/virtio/balloon/virtio_balloon.c
+++ b/sys/dev/virtio/balloon/virtio_balloon.c
@@ -438,8 +438,7 @@ vtballoon_alloc_page(struct vtballoon_softc *sc)
{
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, 0);
vm_page_free(m);
sc->vtballoon_current_npages--;
}
diff --git a/sys/dev/xen/balloon/balloon.c b/sys/dev/xen/balloon/balloon.c
index 2df9c8b..6503a00 100644
--- a/sys/dev/xen/balloon/balloon.c
+++ b/sys/dev/xen/balloon/balloon.c
@@ -94,13 +94,8 @@ SYSCTL_ULONG(_dev_xen_balloon, OID_AUTO, low_mem, CTLFLAG_RD,
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_pages)
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_pages)
}
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_pages)
set_phys_to_machine(pfn, frame_list[i]);
- vm_page_unwire(page, 0);
vm_page_free(page);
}
@@ -286,24 +239,29 @@ decrease_reservation(unsigned long nr_pages)
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, 0);
- 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
OpenPOWER on IntegriCloud