Received: by 2002:a25:ad19:0:0:0:0:0 with SMTP id y25csp9927102ybi; Wed, 24 Jul 2019 12:28:21 -0700 (PDT) X-Google-Smtp-Source: APXvYqySJm1EaYBVANVG7y3t+FerEuMauMoNOzUZVYBRM1thijQHm0M4rCwOC97NU+pKQrP0YqKE X-Received: by 2002:a17:90a:ba94:: with SMTP id t20mr89214772pjr.8.1563996501027; Wed, 24 Jul 2019 12:28:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1563996501; cv=none; d=google.com; s=arc-20160816; b=cnNIk/g47vVBqWSqmtCxUtIufZ8T2SQHhvaLmAHS+Dombz8z9xk+qR4T79VDxLj1+5 SKIKPCw0Qxcvyyr02SvZ8yQGYHWHCVaaea9qEpLIQk2AJ2mNlcOaCdgdKGqek5MZ6wAb et1pgMF7tRyI3aoM029QULNsdm0JtPZSKP4KC8PHQP0NiA1+aNwWQa1niJJdo8O6dWu5 f/oIfedeZiWFMHH0hDufaQsAC1YZ4GXWK/RqjlJ1SDBYI6G2OL4zaHm8kR2l9auGxhI2 Yt78vqr0QhmhQ6tU7j5Yvou6NGJaOYxcBQCU81EpwF/i94fCxFWMMW8p1gicu8MlFNbx LFXQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date; bh=ZTWS8N0ZYovAWvxUKcFKwuBIdI+nBoZkPAQur8PGkGY=; b=0xU11mFuk2kjD/7IRnAeU18srpyD5TK0pj3/IYNHBlbTqHz1E4HsboDzkDLL8uyJIG LSmilLtEnNFaV0mhd/tx9S9113DQLStuHDOWBqp08pPk5WtZa8Z5aC4505k4zbyc4J1p D7/A6NilgSew3cTdFcF+85fGTGytbM0UySipIZSyDO9hTmKb5vmzXCytJPzbWpzY+Y6U ssxxyzrUv2TLR2Rc4XsshBRjICsnVXCIooTRW59cWRh/C5XJU9dgVj7wkPoDOKSIvsWK /slAtjyBNVXISd9OCaqKEfIUq/gHF4ebGQTp5ziagO7KXihnlppyREowRxAjzPJOevzd DJkQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n123si15803748pgn.151.2019.07.24.12.28.06; Wed, 24 Jul 2019 12:28:21 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387515AbfGXTCL (ORCPT + 99 others); Wed, 24 Jul 2019 15:02:11 -0400 Received: from mail-qk1-f193.google.com ([209.85.222.193]:40697 "EHLO mail-qk1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728772AbfGXTCL (ORCPT ); Wed, 24 Jul 2019 15:02:11 -0400 Received: by mail-qk1-f193.google.com with SMTP id s145so34569360qke.7 for ; Wed, 24 Jul 2019 12:02:10 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=ZTWS8N0ZYovAWvxUKcFKwuBIdI+nBoZkPAQur8PGkGY=; b=ic/FCMgJhndTX9taOyRMcaF+SlQBLUAB2nFRjeEZzDCL0jPklY58Mm5hkrE4Ef5cZL /XA+7YxNCC7FemkGWHbq2ePcRWm0607d3aC4zDXqL8k8V/JeMv8xGJpNA0SCJPPCz5yL kv9YfbGUZUErZiz3lN5GyRH7hS2AOmGB5A4IQ56sWIms28Y1SvkgOIstHcGyTHzdHSXh gYlheoG/TY0qSLv6LO8IQBYHfZ2+HPODcaA9jbDsj+958xa8JGvooE7a9JADyvzSf3o+ EclzRgTpLcGADnJGA2jwNmNWtScCIn+4LAdlsFeZJtyyHzoUacbEsUdE0tuihp5mfM19 mZQQ== X-Gm-Message-State: APjAAAVLC+950msuywqHq8oQN4fPbY6tuoZfYZZD2Bs1KYF/iNX0Ogdo 2zwZfQs570g3JrQqReVy0A6vQQ== X-Received: by 2002:a37:743:: with SMTP id 64mr54363029qkh.175.1563994930046; Wed, 24 Jul 2019 12:02:10 -0700 (PDT) Received: from redhat.com (bzq-79-181-91-42.red.bezeqint.net. [79.181.91.42]) by smtp.gmail.com with ESMTPSA id u16sm24131691qte.32.2019.07.24.12.02.03 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Wed, 24 Jul 2019 12:02:08 -0700 (PDT) Date: Wed, 24 Jul 2019 15:02:00 -0400 From: "Michael S. Tsirkin" To: Alexander Duyck Cc: nitesh@redhat.com, kvm@vger.kernel.org, david@redhat.com, dave.hansen@intel.com, linux-kernel@vger.kernel.org, linux-mm@kvack.org, akpm@linux-foundation.org, yang.zhang.wz@gmail.com, pagupta@redhat.com, riel@surriel.com, konrad.wilk@oracle.com, lcapitulino@redhat.com, wei.w.wang@intel.com, aarcange@redhat.com, pbonzini@redhat.com, dan.j.williams@intel.com, alexander.h.duyck@linux.intel.com Subject: Re: [PATCH v2 5/5] virtio-balloon: Add support for providing page hints to host Message-ID: <20190724143902-mutt-send-email-mst@kernel.org> References: <20190724165158.6685.87228.stgit@localhost.localdomain> <20190724170514.6685.17161.stgit@localhost.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20190724170514.6685.17161.stgit@localhost.localdomain> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Jul 24, 2019 at 10:05:14AM -0700, Alexander Duyck wrote: > From: Alexander Duyck > > Add support for the page hinting feature provided by virtio-balloon. > Hinting differs from the regular balloon functionality in that is is > much less durable than a standard memory balloon. Instead of creating a > list of pages that cannot be accessed the pages are only inaccessible > while they are being indicated to the virtio interface. Once the > interface has acknowledged them they are placed back into their respective > free lists and are once again accessible by the guest system. > > Signed-off-by: Alexander Duyck Looking at the design, it seems that hinted pages can immediately be reused. I wonder how we can efficiently support this with kvm when poisoning is in effect. Of course we can just ignore the poison. However it seems cleaner to 1. verify page is poisoned with the correct value 2. fill the page with the correct value on fault Requirement 2 requires some kind of madvise that will save the poison e.g. in the VMA. Not a blocker for sure ... > --- > drivers/virtio/Kconfig | 1 + > drivers/virtio/virtio_balloon.c | 47 +++++++++++++++++++++++++++++++++++ > include/uapi/linux/virtio_balloon.h | 1 + > 3 files changed, 49 insertions(+) > > diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig > index 078615cf2afc..d45556ae1f81 100644 > --- a/drivers/virtio/Kconfig > +++ b/drivers/virtio/Kconfig > @@ -58,6 +58,7 @@ config VIRTIO_BALLOON > tristate "Virtio balloon driver" > depends on VIRTIO > select MEMORY_BALLOON > + select PAGE_HINTING > ---help--- > This driver supports increasing and decreasing the amount > of memory within a KVM guest. > diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c > index 226fbb995fb0..dee9f8f3ad09 100644 > --- a/drivers/virtio/virtio_balloon.c > +++ b/drivers/virtio/virtio_balloon.c > @@ -19,6 +19,7 @@ > #include > #include > #include > +#include > > /* > * Balloon device works in 4K page units. So each page is pointed to by > @@ -27,6 +28,7 @@ > */ > #define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT) > #define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256 > +#define VIRTIO_BALLOON_ARRAY_HINTS_MAX 32 > #define VIRTBALLOON_OOM_NOTIFY_PRIORITY 80 > > #define VIRTIO_BALLOON_FREE_PAGE_ALLOC_FLAG (__GFP_NORETRY | __GFP_NOWARN | \ > @@ -46,6 +48,7 @@ enum virtio_balloon_vq { > VIRTIO_BALLOON_VQ_DEFLATE, > VIRTIO_BALLOON_VQ_STATS, > VIRTIO_BALLOON_VQ_FREE_PAGE, > + VIRTIO_BALLOON_VQ_HINTING, > VIRTIO_BALLOON_VQ_MAX > }; > > @@ -113,6 +116,10 @@ struct virtio_balloon { > > /* To register a shrinker to shrink memory upon memory pressure */ > struct shrinker shrinker; > + > + /* Unused page hinting device */ > + struct virtqueue *hinting_vq; > + struct page_hinting_dev_info ph_dev_info; > }; > > static struct virtio_device_id id_table[] = { > @@ -152,6 +159,22 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq) > > } > > +void virtballoon_page_hinting_react(struct page_hinting_dev_info *ph_dev_info, > + unsigned int num_hints) > +{ > + struct virtio_balloon *vb = > + container_of(ph_dev_info, struct virtio_balloon, ph_dev_info); > + struct virtqueue *vq = vb->hinting_vq; > + unsigned int unused; > + > + /* We should always be able to add these buffers to an empty queue. */ can be an out of memory condition, and then ... > + virtqueue_add_inbuf(vq, ph_dev_info->sg, num_hints, vb, GFP_KERNEL); > + virtqueue_kick(vq); ... this will block forever. > + /* When host has read buffer, this completes via balloon_ack */ > + wait_event(vb->acked, virtqueue_get_buf(vq, &unused)); However below I suggest limiting capacity which will solve this problem for you. > +} > + > static void set_page_pfns(struct virtio_balloon *vb, > __virtio32 pfns[], struct page *page) > { > @@ -476,6 +499,7 @@ static int init_vqs(struct virtio_balloon *vb) > names[VIRTIO_BALLOON_VQ_DEFLATE] = "deflate"; > names[VIRTIO_BALLOON_VQ_STATS] = NULL; > names[VIRTIO_BALLOON_VQ_FREE_PAGE] = NULL; > + names[VIRTIO_BALLOON_VQ_HINTING] = NULL; > > if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { > names[VIRTIO_BALLOON_VQ_STATS] = "stats"; > @@ -487,11 +511,19 @@ static int init_vqs(struct virtio_balloon *vb) > callbacks[VIRTIO_BALLOON_VQ_FREE_PAGE] = NULL; > } > > + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_HINTING)) { > + names[VIRTIO_BALLOON_VQ_HINTING] = "hinting_vq"; > + callbacks[VIRTIO_BALLOON_VQ_HINTING] = balloon_ack; > + } > + > err = vb->vdev->config->find_vqs(vb->vdev, VIRTIO_BALLOON_VQ_MAX, > vqs, callbacks, names, NULL, NULL); > if (err) > return err; > > + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_HINTING)) > + vb->hinting_vq = vqs[VIRTIO_BALLOON_VQ_HINTING]; > + > vb->inflate_vq = vqs[VIRTIO_BALLOON_VQ_INFLATE]; > vb->deflate_vq = vqs[VIRTIO_BALLOON_VQ_DEFLATE]; > if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { > @@ -924,12 +956,24 @@ static int virtballoon_probe(struct virtio_device *vdev) > if (err) > goto out_del_balloon_wq; > } > + > + vb->ph_dev_info.react = virtballoon_page_hinting_react; > + vb->ph_dev_info.capacity = VIRTIO_BALLOON_ARRAY_HINTS_MAX; As explained above I think you should limit this by vq size. Otherwise virtqueue add buf might fail. In fact by struct spec reading you need to limit it anyway otherwise it will fail unconditionally. In practice on most hypervisors it will typically work ... > + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_HINTING)) { > + err = page_hinting_startup(&vb->ph_dev_info); > + if (err) > + goto out_unregister_shrinker; > + } > + > virtio_device_ready(vdev); > > if (towards_target(vb)) > virtballoon_changed(vdev); > return 0; > > +out_unregister_shrinker: > + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) > + virtio_balloon_unregister_shrinker(vb); > out_del_balloon_wq: > if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) > destroy_workqueue(vb->balloon_wq); > @@ -958,6 +1002,8 @@ static void virtballoon_remove(struct virtio_device *vdev) > { > struct virtio_balloon *vb = vdev->priv; > > + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_HINTING)) > + page_hinting_shutdown(&vb->ph_dev_info); > if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) > virtio_balloon_unregister_shrinker(vb); > spin_lock_irq(&vb->stop_update_lock); > @@ -1027,6 +1073,7 @@ static int virtballoon_validate(struct virtio_device *vdev) > VIRTIO_BALLOON_F_DEFLATE_ON_OOM, > VIRTIO_BALLOON_F_FREE_PAGE_HINT, > VIRTIO_BALLOON_F_PAGE_POISON, > + VIRTIO_BALLOON_F_HINTING, > }; > > static struct virtio_driver virtio_balloon_driver = { > diff --git a/include/uapi/linux/virtio_balloon.h b/include/uapi/linux/virtio_balloon.h > index a1966cd7b677..2b0f62814e22 100644 > --- a/include/uapi/linux/virtio_balloon.h > +++ b/include/uapi/linux/virtio_balloon.h > @@ -36,6 +36,7 @@ > #define VIRTIO_BALLOON_F_DEFLATE_ON_OOM 2 /* Deflate balloon on OOM */ > #define VIRTIO_BALLOON_F_FREE_PAGE_HINT 3 /* VQ to report free pages */ > #define VIRTIO_BALLOON_F_PAGE_POISON 4 /* Guest is using page poisoning */ > +#define VIRTIO_BALLOON_F_HINTING 5 /* Page hinting virtqueue */ > > /* Size of a PFN in the balloon interface. */ > #define VIRTIO_BALLOON_PFN_SHIFT 12