From patchwork Thu Apr 12 05:36:35 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 151967 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id E41E9B707D for ; Thu, 12 Apr 2012 15:37:14 +1000 (EST) Received: from localhost ([::1]:45043 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SICiW-0007tJ-KY for incoming@patchwork.ozlabs.org; Thu, 12 Apr 2012 01:37:12 -0400 Received: from eggs.gnu.org ([208.118.235.92]:39433) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SICiF-0007kh-Ot for qemu-devel@nongnu.org; Thu, 12 Apr 2012 01:36:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SICiC-0007Vh-9B for qemu-devel@nongnu.org; Thu, 12 Apr 2012 01:36:55 -0400 Received: from ozlabs.org ([203.10.76.45]:34765) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SICiB-0007Uz-Ll for qemu-devel@nongnu.org; Thu, 12 Apr 2012 01:36:52 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 38281B70A1; Thu, 12 Apr 2012 15:36:47 +1000 (EST) From: David Gibson To: rusty@rustcorp.com.au, mst@redhat.com Date: Thu, 12 Apr 2012 15:36:35 +1000 Message-Id: <1334208995-29985-4-git-send-email-david@gibson.dropbear.id.au> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1334208995-29985-1-git-send-email-david@gibson.dropbear.id.au> References: <1334208995-29985-1-git-send-email-david@gibson.dropbear.id.au> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 203.10.76.45 Cc: qemu-devel@nongnu.org, David Gibson , paulus@samba.org, linux-kernel@vger.kernel.org, virtualization@lists.linux-foundation.org Subject: [Qemu-devel] [PATCH 3/3] virtio_balloon: Bugfixes for PAGE_SIZE != 4k X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The virtio_balloon device is specced to always operate on 4k pages. The virtio_balloon driver has a feeble attempt at reconciling this with a lerge kernel page size, but it is (a) exactly wrong (it shifts the pfn in the wrong direction) and (b) insufficient (it doesn't issue multiple 4k balloon requests for each guest page, or correct other accounting values for the different in page size). This patch fixes the various problems. It has been tested with a powerpc guest kernel configured for 64kB base page size, running under qemu. Signed-off-by: David Gibson --- drivers/virtio/virtio_balloon.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 553cc1f..834b7f9 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -60,13 +60,20 @@ static struct virtio_device_id id_table[] = { { 0 }, }; -static u32 page_to_balloon_pfn(struct page *page) +#define BALLOON_PAGE_ORDER (PAGE_SHIFT - VIRTIO_BALLOON_PFN_SHIFT) +#define PAGES_PER_ARRAY(_a) (ARRAY_SIZE(_a) >> BALLOON_PAGE_ORDER) + +static void page_to_balloon_pfns(u32 pfns[], unsigned int n, struct page *page) { - unsigned long pfn = page_to_pfn(page); + unsigned long bpfn = page_to_pfn(page) << BALLOON_PAGE_ORDER; + u32 *p = &pfns[n << BALLOON_PAGE_ORDER]; + int i; BUILD_BUG_ON(PAGE_SHIFT < VIRTIO_BALLOON_PFN_SHIFT); - /* Convert pfn from Linux page size to balloon page size. */ - return pfn >> (PAGE_SHIFT - VIRTIO_BALLOON_PFN_SHIFT); + + /* Enter a balloon pfn for each 4k subpage of the Linux page */ + for (i = 0; i < (1 << BALLOON_PAGE_ORDER); i++) + p[i] = bpfn + i; } static void balloon_ack(struct virtqueue *vq) @@ -84,7 +91,8 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq, { struct scatterlist sg; - sg_init_one(&sg, vb->pfns, sizeof(vb->pfns[0]) * n); + sg_init_one(&sg, vb->pfns, + sizeof(vb->pfns[0]) * (n << BALLOON_PAGE_ORDER)); init_completion(&vb->acked); @@ -102,7 +110,7 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num) unsigned int n; /* We can only do one array worth at a time. */ - num = min(num, ARRAY_SIZE(vb->pfns)); + num = min(num, PAGES_PER_ARRAY(vb->pfns)); for (n = 0; n < num; n++) { struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY | @@ -116,7 +124,7 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num) msleep(200); break; } - vb->pfns[n] = page_to_balloon_pfn(page); + page_to_balloon_pfns(vb->pfns, n, page); totalram_pages--; vb->num_pages++; list_add(&page->lru, &vb->pages); @@ -134,7 +142,7 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num) unsigned int i; for (i = 0; i < num; i++) { - __free_page(pfn_to_page(pfns[i])); + __free_page(pfn_to_page(pfns[i << BALLOON_PAGE_ORDER])); totalram_pages++; } } @@ -145,12 +153,12 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num) unsigned int n; /* We can only do one array worth at a time. */ - num = min(num, ARRAY_SIZE(vb->pfns)); + num = min(num, PAGES_PER_ARRAY(vb->pfns)); for (n = 0; n < num; n++) { page = list_first_entry(&vb->pages, struct page, lru); list_del(&page->lru); - vb->pfns[n] = page_to_balloon_pfn(page); + page_to_balloon_pfns(vb->pfns, n, page); vb->num_pages--; } @@ -244,13 +252,13 @@ static inline s64 towards_target(struct virtio_balloon *vb) vb->vdev->config->get(vb->vdev, offsetof(struct virtio_balloon_config, num_pages), &v, sizeof(v)); - target = le32_to_cpu(v); + target = le32_to_cpu(v) >> BALLOON_PAGE_ORDER; return target - vb->num_pages; } static void update_balloon_size(struct virtio_balloon *vb) { - __le32 actual = cpu_to_le32(vb->num_pages); + __le32 actual = cpu_to_le32(vb->num_pages << BALLOON_PAGE_ORDER); vb->vdev->config->set(vb->vdev, offsetof(struct virtio_balloon_config, actual),