2008-12-04 23:33:06 +03:00
|
|
|
/*
|
|
|
|
* Virtio Support
|
|
|
|
*
|
|
|
|
* Copyright IBM, Corp. 2007-2008
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Anthony Liguori <aliguori@us.ibm.com>
|
|
|
|
* Rusty Russell <rusty@rustcorp.com.au>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2. See
|
|
|
|
* the COPYING file in the top-level directory.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2016-06-29 14:47:03 +03:00
|
|
|
#ifndef QEMU_VIRTIO_BALLOON_H
|
|
|
|
#define QEMU_VIRTIO_BALLOON_H
|
2008-12-04 23:33:06 +03:00
|
|
|
|
2015-02-17 00:35:52 +03:00
|
|
|
#include "standard-headers/linux/virtio_balloon.h"
|
2013-02-05 20:06:20 +04:00
|
|
|
#include "hw/virtio/virtio.h"
|
2018-12-11 11:24:53 +03:00
|
|
|
#include "sysemu/iothread.h"
|
2008-12-04 23:33:06 +03:00
|
|
|
|
2013-04-09 14:04:48 +04:00
|
|
|
#define TYPE_VIRTIO_BALLOON "virtio-balloon-device"
|
2013-03-27 13:49:10 +04:00
|
|
|
#define VIRTIO_BALLOON(obj) \
|
|
|
|
OBJECT_CHECK(VirtIOBalloon, (obj), TYPE_VIRTIO_BALLOON)
|
|
|
|
|
2018-12-11 11:24:53 +03:00
|
|
|
#define VIRTIO_BALLOON_FREE_PAGE_REPORT_CMD_ID_MIN 0x80000000
|
|
|
|
|
2015-02-17 00:35:52 +03:00
|
|
|
typedef struct virtio_balloon_stat VirtIOBalloonStat;
|
2010-01-26 23:17:35 +03:00
|
|
|
|
2015-06-04 13:34:31 +03:00
|
|
|
typedef struct virtio_balloon_stat_modern {
|
|
|
|
uint16_t tag;
|
|
|
|
uint8_t reserved[6];
|
|
|
|
uint64_t val;
|
|
|
|
} VirtIOBalloonStatModern;
|
|
|
|
|
virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size
The virtio-balloon always works in units of 4kiB (BALLOON_PAGE_SIZE), but
we can only actually discard memory in units of the host page size.
Now, we handle this very badly: we silently ignore balloon requests that
aren't host page aligned, and for requests that are host page aligned we
discard the entire host page. The latter can corrupt guest memory if its
page size is smaller than the host's.
The obvious choice would be to disable the balloon if the host page size is
not 4kiB. However, that would break the special case where host and guest
have the same page size, but that's larger than 4kiB. That case currently
works by accident[1] - and is used in practice on many production POWER
systems where 64kiB has long been the Linux default page size on both host
and guest.
To make the balloon safe, without breaking that useful special case, we
need to accumulate 4kiB balloon requests until we have a whole contiguous
host page to discard.
We could in principle do that across all guest memory, but it would require
a large bitmap to track. This patch represents a compromise: we track
ballooned subpages for a single contiguous host page at a time. This means
that if the guest discards all 4kiB chunks of a host page in succession,
we will discard it. This is the expected behaviour in the (host page) ==
(guest page) != 4kiB case we want to support.
If the guest scatters 4kiB requests across different host pages, we don't
discard anything, and issue a warning. Not ideal, but at least we don't
corrupt guest memory as the previous version could.
Warning reporting is kind of a compromise here. Determining whether we're
in a problematic state at realize() time is tricky, because we'd have to
look at the host pagesizes of all memory backends, but we can't really know
if some of those backends could be for special purpose memory that's not
subject to ballooning.
Reporting only when the guest tries to balloon a partial page also isn't
great because if the guest page size happens to line up it won't indicate
that we're in a non ideal situation. It could also cause alarming repeated
warnings whenever a migration is attempted.
So, what we do is warn the first time the guest attempts balloon a partial
host page, whether or not it will end up ballooning the rest of the page
immediately afterwards.
[1] Because when the guest attempts to balloon a page, it will submit
requests for each 4kiB subpage. Most will be ignored, but the one
which happens to be host page aligned will discard the whole lot.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20190214043916.22128-6-david@gibson.dropbear.id.au>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2019-02-14 07:39:16 +03:00
|
|
|
typedef struct PartiallyBalloonedPage PartiallyBalloonedPage;
|
|
|
|
|
2018-12-11 11:24:53 +03:00
|
|
|
enum virtio_balloon_free_page_report_status {
|
|
|
|
FREE_PAGE_REPORT_S_STOP = 0,
|
|
|
|
FREE_PAGE_REPORT_S_REQUESTED = 1,
|
|
|
|
FREE_PAGE_REPORT_S_START = 2,
|
|
|
|
FREE_PAGE_REPORT_S_DONE = 3,
|
|
|
|
};
|
|
|
|
|
2013-03-18 20:37:18 +04:00
|
|
|
typedef struct VirtIOBalloon {
|
2013-03-27 13:49:14 +04:00
|
|
|
VirtIODevice parent_obj;
|
2018-12-11 11:24:53 +03:00
|
|
|
VirtQueue *ivq, *dvq, *svq, *free_page_vq;
|
|
|
|
uint32_t free_page_report_status;
|
2013-03-18 20:37:18 +04:00
|
|
|
uint32_t num_pages;
|
|
|
|
uint32_t actual;
|
2018-12-11 11:24:53 +03:00
|
|
|
uint32_t free_page_report_cmd_id;
|
2013-03-18 20:37:18 +04:00
|
|
|
uint64_t stats[VIRTIO_BALLOON_S_NR];
|
2016-02-04 17:26:51 +03:00
|
|
|
VirtQueueElement *stats_vq_elem;
|
2013-03-18 20:37:18 +04:00
|
|
|
size_t stats_vq_offset;
|
|
|
|
QEMUTimer *stats_timer;
|
2018-12-11 11:24:53 +03:00
|
|
|
IOThread *iothread;
|
|
|
|
QEMUBH *free_page_bh;
|
|
|
|
/*
|
|
|
|
* Lock to synchronize threads to access the free page reporting related
|
|
|
|
* fields (e.g. free_page_report_status).
|
|
|
|
*/
|
|
|
|
QemuMutex free_page_lock;
|
|
|
|
QemuCond free_page_cond;
|
|
|
|
/*
|
|
|
|
* Set to block iothread to continue reading free page hints as the VM is
|
|
|
|
* stopped.
|
|
|
|
*/
|
|
|
|
bool block_iothread;
|
|
|
|
NotifierWithReturn free_page_report_notify;
|
2013-03-18 20:37:18 +04:00
|
|
|
int64_t stats_last_update;
|
|
|
|
int64_t stats_poll_interval;
|
2015-06-15 13:52:52 +03:00
|
|
|
uint32_t host_features;
|
virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size
The virtio-balloon always works in units of 4kiB (BALLOON_PAGE_SIZE), but
we can only actually discard memory in units of the host page size.
Now, we handle this very badly: we silently ignore balloon requests that
aren't host page aligned, and for requests that are host page aligned we
discard the entire host page. The latter can corrupt guest memory if its
page size is smaller than the host's.
The obvious choice would be to disable the balloon if the host page size is
not 4kiB. However, that would break the special case where host and guest
have the same page size, but that's larger than 4kiB. That case currently
works by accident[1] - and is used in practice on many production POWER
systems where 64kiB has long been the Linux default page size on both host
and guest.
To make the balloon safe, without breaking that useful special case, we
need to accumulate 4kiB balloon requests until we have a whole contiguous
host page to discard.
We could in principle do that across all guest memory, but it would require
a large bitmap to track. This patch represents a compromise: we track
ballooned subpages for a single contiguous host page at a time. This means
that if the guest discards all 4kiB chunks of a host page in succession,
we will discard it. This is the expected behaviour in the (host page) ==
(guest page) != 4kiB case we want to support.
If the guest scatters 4kiB requests across different host pages, we don't
discard anything, and issue a warning. Not ideal, but at least we don't
corrupt guest memory as the previous version could.
Warning reporting is kind of a compromise here. Determining whether we're
in a problematic state at realize() time is tricky, because we'd have to
look at the host pagesizes of all memory backends, but we can't really know
if some of those backends could be for special purpose memory that's not
subject to ballooning.
Reporting only when the guest tries to balloon a partial page also isn't
great because if the guest page size happens to line up it won't indicate
that we're in a non ideal situation. It could also cause alarming repeated
warnings whenever a migration is attempted.
So, what we do is warn the first time the guest attempts balloon a partial
host page, whether or not it will end up ballooning the rest of the page
immediately afterwards.
[1] Because when the guest attempts to balloon a page, it will submit
requests for each 4kiB subpage. Most will be ignored, but the one
which happens to be host page aligned will discard the whole lot.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20190214043916.22128-6-david@gibson.dropbear.id.au>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2019-02-14 07:39:16 +03:00
|
|
|
PartiallyBalloonedPage *pbp;
|
2019-07-10 17:14:40 +03:00
|
|
|
|
|
|
|
bool qemu_4_0_config_size;
|
2013-03-18 20:37:18 +04:00
|
|
|
} VirtIOBalloon;
|
|
|
|
|
2008-12-04 23:33:06 +03:00
|
|
|
#endif
|