From patchwork Fri Apr 10 03:41:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Duyck X-Patchwork-Id: 284490 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 18C95C2BB1D for ; Fri, 10 Apr 2020 03:42:55 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D9A50206DD for ; Fri, 10 Apr 2020 03:42:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ISc143uM" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D9A50206DD Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:58182 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jMkZC-0003Dx-0G for qemu-devel@archiver.kernel.org; Thu, 09 Apr 2020 23:42:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:47816) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jMkY7-0001Qd-Gm for qemu-devel@nongnu.org; Thu, 09 Apr 2020 23:41:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1jMkY6-0007tH-6r for qemu-devel@nongnu.org; Thu, 09 Apr 2020 23:41:47 -0400 Received: from mail-qv1-xf42.google.com ([2607:f8b0:4864:20::f42]:43740) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1jMkY6-0007tA-2C for qemu-devel@nongnu.org; Thu, 09 Apr 2020 23:41:46 -0400 Received: by mail-qv1-xf42.google.com with SMTP id w26so418161qvd.10 for ; Thu, 09 Apr 2020 20:41:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=subject:from:to:cc:date:message-id:in-reply-to:references :user-agent:mime-version:content-transfer-encoding; bh=VkROvCgm5mN7+wKVn1WvkxoHIcp7705QcSzcumM/77U=; b=ISc143uM/ga32qp3ovR6UzCUshCKaA0mBjjDNdkCju7rwK1K2fZbDJjOWIgD8/rV7J gvO52e7W/kr7xAeTDUCRErYaJlrZTnMZIFxYptnbdWvB+MDXWvXDd12DTBhSo4OE0flX xq97WlnkTn1wboUDHgpjCGP/zd7q1ZfHn3UCMejt1DHdPMPUl3iRx2k+6t/TIueATse6 j5JhCx+LK1a2GupiCVuF80p+nTi0hALTttvkwjFDA7fM9rr2PBfJJTz9RnnGHWLXeGZw YKejpMXsoPgV1gug5pAiPNmTGNUd3OUXihsctQpJ6hivhF0yo+0RGiQnb8IetHwVSnXW syvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:cc:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=VkROvCgm5mN7+wKVn1WvkxoHIcp7705QcSzcumM/77U=; b=ifVLc8I9fCFP8AwyjF5Tf53/XwUyYv5PrNduSYzteMPQ4UKdQRNrOxTYXQ2s3xcite oNmoDqAHMHUtLLDeOQre+Ztewh69C+PF5uy5vaB6tfkh5zE/AkMmjIHtRVx8ZBgdzr5N lLRu8UlM7NzGX6QCkh1tUnEymDnDdlVLF2SBxqDhkCHCWQlWnyWVheXszZtftaICoCT3 IXWkH6nhJ0dPRRWScEXPWrVRM9C2STDA+1qZ18NELUXQpW4wflpxBYqXgCp73C7bgti5 c7xknOXWn3r4SnH5MYRbwAuT+ilcsSBfCS1IuNNcKXBNkKz7n4dMkAjkBVCbVQnJla2t FPNA== X-Gm-Message-State: AGi0Pua53y3W6sMwxEC+G758Mv8zwMZYkLpSJfgj7BpGMRtMtCcCXraE lKJp6ysCFBAtsL18kChQ8ancZr7e3/k= X-Google-Smtp-Source: APiQypJacHOkOh+e3nkYmp7fHoEVrchfHBgzoPPxyKoplIYyKnOSI6c9Nl9xYdo7Y/L03J2R2hRrsg== X-Received: by 2002:ad4:4e6a:: with SMTP id ec10mr3465375qvb.204.1586490105160; Thu, 09 Apr 2020 20:41:45 -0700 (PDT) Received: from localhost.localdomain ([2001:470:b:9c3:9e5c:8eff:fe4f:f2d0]) by smtp.gmail.com with ESMTPSA id f68sm695131qtb.19.2020.04.09.20.41.44 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 09 Apr 2020 20:41:44 -0700 (PDT) Subject: [PATCH v19 QEMU 3/4] virtio-balloon: Provide an interface for free page reporting From: Alexander Duyck To: pbonzini@redhat.com, david@redhat.com, mst@redhat.com Date: Thu, 09 Apr 2020 20:41:43 -0700 Message-ID: <20200410034143.24738.78852.stgit@localhost.localdomain> In-Reply-To: <20200410033729.24738.22879.stgit@localhost.localdomain> References: <20200410033729.24738.22879.stgit@localhost.localdomain> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::f42 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: virtio-dev@lists.oasis-open.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Alexander Duyck Add support for free page reporting. The idea is to function very similar to how the balloon works in that we basically end up madvising the page as not being used. However we don't really need to bother with any deflate type logic since the page will be faulted back into the guest when it is read or written to. This provides a new way of letting the guest proactively report free pages to the hypervisor, so the hypervisor can reuse them. In contrast to inflate/deflate that is triggered via the hypervisor explicitly. Signed-off-by: Alexander Duyck --- hw/virtio/virtio-balloon.c | 63 +++++++++++++++++++++++++++++++++++- include/hw/virtio/virtio-balloon.h | 2 + 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index 1c6d36a29a04..86d8b48a8e3a 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -321,6 +321,57 @@ static void balloon_stats_set_poll_interval(Object *obj, Visitor *v, balloon_stats_change_timer(s, 0); } +static void virtio_balloon_handle_report(VirtIODevice *vdev, VirtQueue *vq) +{ + VirtIOBalloon *dev = VIRTIO_BALLOON(vdev); + VirtQueueElement *elem; + + while ((elem = virtqueue_pop(vq, sizeof(VirtQueueElement)))) { + unsigned int i; + + for (i = 0; i < elem->in_num; i++) { + void *addr = elem->in_sg[i].iov_base; + size_t size = elem->in_sg[i].iov_len; + ram_addr_t ram_offset; + size_t rb_page_size; + RAMBlock *rb; + + if (qemu_balloon_is_inhibited() || dev->poison_val) { + continue; + } + + /* + * There is no need to check the memory section to see if + * it is ram/readonly/romd like there is for handle_output + * below. If the region is not meant to be written to then + * address_space_map will have allocated a bounce buffer + * and it will be freed in address_space_unmap and trigger + * and unassigned_mem_write before failing to copy over the + * buffer. If more than one bad descriptor is provided it + * will return NULL after the first bounce buffer and fail + * to map any resources. + */ + rb = qemu_ram_block_from_host(addr, false, &ram_offset); + if (!rb) { + trace_virtio_balloon_bad_addr(elem->in_addr[i]); + continue; + } + + /* For now we will simply ignore unaligned memory regions */ + rb_page_size = qemu_ram_pagesize(rb); + if (!QEMU_IS_ALIGNED(ram_offset | size, rb_page_size)) { + continue; + } + + ram_block_discard_range(rb, ram_offset, size); + } + + virtqueue_push(vq, elem, 0); + virtio_notify(vdev, vq); + g_free(elem); + } +} + static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) { VirtIOBalloon *s = VIRTIO_BALLOON(vdev); @@ -628,7 +679,8 @@ static size_t virtio_balloon_config_size(VirtIOBalloon *s) return sizeof(struct virtio_balloon_config); } if (virtio_has_feature(features, VIRTIO_BALLOON_F_PAGE_POISON) || - virtio_has_feature(features, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { + virtio_has_feature(features, VIRTIO_BALLOON_F_FREE_PAGE_HINT) || + virtio_has_feature(features, VIRTIO_BALLOON_F_REPORTING)) { return sizeof(struct virtio_balloon_config); } return offsetof(struct virtio_balloon_config, free_page_report_cmd_id); @@ -717,7 +769,8 @@ static uint64_t virtio_balloon_get_features(VirtIODevice *vdev, uint64_t f, VirtIOBalloon *dev = VIRTIO_BALLOON(vdev); f |= dev->host_features; virtio_add_feature(&f, VIRTIO_BALLOON_F_STATS_VQ); - if (virtio_has_feature(f, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { + if (virtio_has_feature(f, VIRTIO_BALLOON_F_FREE_PAGE_HINT) || + virtio_has_feature(f, VIRTIO_BALLOON_F_REPORTING)) { virtio_add_feature(&f, VIRTIO_BALLOON_F_PAGE_POISON); } @@ -807,6 +860,10 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp) s->dvq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output); s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats); + if (virtio_has_feature(s->host_features, VIRTIO_BALLOON_F_REPORTING)) { + s->rvq = virtio_add_queue(vdev, 32, virtio_balloon_handle_report); + } + if (virtio_has_feature(s->host_features, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { s->free_page_vq = virtio_add_queue(vdev, VIRTQUEUE_MAX_SIZE, @@ -940,6 +997,8 @@ static Property virtio_balloon_properties[] = { */ DEFINE_PROP_BOOL("qemu-4-0-config-size", VirtIOBalloon, qemu_4_0_config_size, false), + DEFINE_PROP_BIT("free-page-reporting", VirtIOBalloon, host_features, + VIRTIO_BALLOON_F_REPORTING, true), DEFINE_PROP_LINK("iothread", VirtIOBalloon, iothread, TYPE_IOTHREAD, IOThread *), DEFINE_PROP_END_OF_LIST(), diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h index 7fe78e5c14d7..db5bf7127112 100644 --- a/include/hw/virtio/virtio-balloon.h +++ b/include/hw/virtio/virtio-balloon.h @@ -42,7 +42,7 @@ enum virtio_balloon_free_page_report_status { typedef struct VirtIOBalloon { VirtIODevice parent_obj; - VirtQueue *ivq, *dvq, *svq, *free_page_vq; + VirtQueue *ivq, *dvq, *svq, *free_page_vq, *rvq; uint32_t free_page_report_status; uint32_t num_pages; uint32_t actual;