From: Marcelo Tosatti <marcelo-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org>
To: Anthony Liguori <aliguori-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Cc: kvm-devel <kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Subject: [PATCH] QEMU KVM balloon support (v2)
Date: Wed, 9 Jan 2008 16:26:11 -0200 [thread overview]
Message-ID: <20080109182611.GD303@dmt> (raw)
QEMU support for ballooning.
Changes:
- Use int64_t for memory size input, otherwise it wraps around
at 2GB (Daniel Berrange)
- Use virtio_update_config()
- Remove save/load hooks, they will be rewritten after Anthony introduces
proper virtio s/l support
Index: kvm-userspace/libkvm/libkvm.c
===================================================================
--- kvm-userspace.orig/libkvm/libkvm.c
+++ kvm-userspace/libkvm/libkvm.c
@@ -886,6 +886,17 @@ int kvm_is_ready_for_interrupt_injection
return run->ready_for_interrupt_injection;
}
+int kvm_sync_shadow_with_user(kvm_context_t kvm)
+{
+ int r = 0;
+#ifdef KVM_CAP_SYNC_SHADOW_WITH_USER
+ r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_SYNC_SHADOW_WITH_USER);
+ if (r > 0)
+ r = ioctl(kvm->vm_fd, KVM_SYNC_SHADOW_WITH_USER);
+#endif
+ return r;
+}
+
int kvm_run(kvm_context_t kvm, int vcpu)
{
int r;
Index: kvm-userspace/libkvm/libkvm.h
===================================================================
--- kvm-userspace.orig/libkvm/libkvm.h
+++ kvm-userspace/libkvm/libkvm.h
@@ -423,6 +423,8 @@ int kvm_get_dirty_pages_range(kvm_contex
int (*cb)(unsigned long start, unsigned long len,
void*bitmap, void *opaque));
+int kvm_sync_shadow_with_user(kvm_context_t kvm);
+
/*!
* \brief Create a memory alias
*
Index: kvm-userspace/qemu/Makefile.target
===================================================================
--- kvm-userspace.orig/qemu/Makefile.target
+++ kvm-userspace/qemu/Makefile.target
@@ -464,7 +464,7 @@ VL_OBJS += rtl8139.o
VL_OBJS+= hypercall.o
# virtio devices
-VL_OBJS += virtio.o virtio-net.o virtio-blk.o
+VL_OBJS += virtio.o virtio-net.o virtio-blk.o virtio-balloon.o
ifeq ($(TARGET_BASE_ARCH), i386)
# Hardware support
Index: kvm-userspace/qemu/hw/pc.c
===================================================================
--- kvm-userspace.orig/qemu/hw/pc.c
+++ kvm-userspace/qemu/hw/pc.c
@@ -1029,6 +1029,8 @@ static void pc_init1(ram_addr_t ram_size
}
}
+ virtio_balloon_init(pci_bus);
+
#define USE_HYPERCALL
#ifdef USE_HYPERCALL
pci_hypercall_init(pci_bus);
Index: kvm-userspace/qemu/hw/pc.h
===================================================================
--- kvm-userspace.orig/qemu/hw/pc.h
+++ kvm-userspace/qemu/hw/pc.h
@@ -155,4 +155,7 @@ void *virtio_blk_init(PCIBus *bus, uint1
void extboot_init(BlockDriverState *bs, int cmd);
+/* virtio-balloon.c */
+void *virtio_balloon_init(PCIBus *bus);
+
#endif
Index: kvm-userspace/qemu/hw/virtio-balloon.c
===================================================================
--- /dev/null
+++ kvm-userspace/qemu/hw/virtio-balloon.c
@@ -0,0 +1,84 @@
+#include "virtio.h"
+#include "pc.h"
+#include "console.h"
+#include "qemu-kvm.h"
+#include <linux/virtio_balloon.h>
+
+typedef struct VirtIOBalloon
+{
+ VirtIODevice vdev;
+} VirtIOBalloon;
+
+VirtIOBalloon *virtio_balloon;
+
+extern int64_t ram_size;
+int64_t target_ramsize;
+
+static void virtio_balloon_queue(VirtIODevice *vdev, VirtQueue *vq)
+{
+ VirtQueueElement elem;
+
+ while (virtqueue_pop(vq, &elem)) {
+ int r;
+ size_t len = 0;
+ struct virtio_balloon_hdr *hdr;
+ void *data;
+
+ hdr = (void *)elem.in_sg[0].iov_base;
+ switch(hdr->cmd) {
+ case CMD_BALLOON_INFLATE:
+ case CMD_BALLOON_DEFLATE:
+ data = elem.in_sg[1].iov_base;
+ len = elem.in_sg[1].iov_len;
+
+ r = kvm_handle_ballooning_call(data, len);
+ hdr->status = (uint8_t) r;
+ break;
+ default:
+ fprintf(stderr, "unknown command %x\n",
+ hdr->cmd);
+ hdr->status = 1;
+ }
+ len += sizeof(struct virtio_balloon_hdr);
+ virtqueue_push(vq, &elem, len);
+ virtio_notify(vdev, vq);
+ }
+}
+
+static void virtio_balloon_update_config(VirtIODevice *vdev, uint8_t *config)
+{
+ struct virtio_balloon_config cfg;
+
+ cfg.target_nrpages = target_ramsize / TARGET_PAGE_SIZE;
+
+ memcpy(config, &cfg, sizeof(cfg));
+}
+
+void *virtio_balloon_init(PCIBus *bus)
+{
+ VirtIOBalloon *n;
+
+ /* XXX: pif=0x80? */
+ n = (VirtIOBalloon *)virtio_init_pci(bus, "virtio-kvm-balloon", 0x1AF4,
+ 0x1003, 0, VIRTIO_ID_BALLOON,
+ 0xff, 0x80, 0x00, 4,
+ sizeof(VirtIOBalloon));
+
+ virtio_add_queue(&n->vdev, 128, virtio_balloon_queue);
+
+ n->vdev.update_config = virtio_balloon_update_config;
+ target_ramsize = ram_size;
+ virtio_balloon = n;
+
+ return &n->vdev;
+}
+
+int balloon_update_target(int64_t target)
+{
+ VirtIODevice *vdev = &virtio_balloon->vdev;
+ target_ramsize = target;
+
+ virtio_update_config(vdev);
+
+ return 0;
+}
Index: kvm-userspace/qemu/migration.c
===================================================================
--- kvm-userspace.orig/qemu/migration.c
+++ kvm-userspace/qemu/migration.c
@@ -34,6 +34,7 @@
#endif
#include <sys/wait.h>
+#include <sys/mman.h>
#define MIN_FINALIZE_SIZE (200 << 10)
#define MAX_ITERATIONS 30
@@ -765,6 +766,9 @@ static void migrate_incoming_homogeneous
for (i=0; i<n; i++)
p[i] = v;
+
+ if (v == 0)
+ madvise(phys_ram_base + addr, TARGET_PAGE_SIZE, MADV_DONTNEED);
}
static int migrate_incoming_page(QEMUFile *f, uint32_t addr)
Index: kvm-userspace/qemu/monitor.c
===================================================================
--- kvm-userspace.orig/qemu/monitor.c
+++ kvm-userspace/qemu/monitor.c
@@ -1339,6 +1339,8 @@ static term_cmd_t term_cmds[] = {
"", "cancel the current VM migration" },
{ "migrate_set_speed", "s", do_migrate_set_speed,
"value", "set maximum speed (in bytes) for migrations" },
+ { "setmem", "s", do_setmemory, "value",
+ "set memory for the guest (in bytes)" },
{ NULL, NULL, },
};
Index: kvm-userspace/qemu/qemu-kvm.c
===================================================================
--- kvm-userspace.orig/qemu/qemu-kvm.c
+++ kvm-userspace/qemu/qemu-kvm.c
@@ -21,6 +21,7 @@ int kvm_irqchip = 1;
#include <libkvm.h>
#include <pthread.h>
#include <sys/utsname.h>
+#include <sys/mman.h>
extern void perror(const char *s);
@@ -513,7 +514,74 @@ static int kvm_shutdown(void *opaque, in
qemu_system_reset_request();
return 1;
}
-
+
+static int do_balloon_on_page(unsigned int gfn, int is_inflate)
+{
+ unsigned long addr = gfn * TARGET_PAGE_SIZE;
+ unsigned char *curr_addr = phys_ram_base + addr;
+ int r;
+ int advice = is_inflate ? MADV_DONTNEED : MADV_NORMAL;
+
+ r = madvise(curr_addr, TARGET_PAGE_SIZE, advice);
+
+ if (r < 0) {
+ perror("madvise");
+ fprintf(stderr, "%s: gfn=0x%x is_inflate=%d mlock/madvise: failed\n",
+ __FUNCTION__, gfn, is_inflate);
+ }
+ return r;
+}
+
+int kvm_handle_ballooning_call(void *data, size_t len)
+{
+ unsigned int gfn;
+ unsigned int *curr_pfn;
+ int is_inflate;
+ int req_npages, npages;
+ int i, r = 0, saved_r = 0;
+
+ curr_pfn = data;
+
+ req_npages = (int)*curr_pfn++;
+
+ npages = abs(req_npages);
+ is_inflate = (req_npages > 0);
+
+ if (is_inflate)
+ kvm_sync_shadow_with_user(kvm_context);
+
+ for (i = 0; i < npages; i++, curr_pfn++) {
+ gfn = *curr_pfn;
+
+ r = do_balloon_on_page(gfn, is_inflate);
+ if (r) {
+ printf("do_balloon_on_page FAILED, gfn=0x%x, is_inflate=%d\n",
+ gfn, is_inflate);
+ goto out_failed;
+ }
+ }
+
+ return r;
+
+out_failed:
+ npages = i;
+ curr_pfn = data;
+ curr_pfn++;
+ saved_r = r;
+
+ for (i = 0; i<npages; i++, curr_pfn++) {
+ gfn = *curr_pfn;
+
+ r = do_balloon_on_page(gfn, !is_inflate);
+ if (r) {
+ printf("do_balloon_on_page EH FAILED, gfn=0x%x, is_inflate=%d\n",
+ gfn, !is_inflate);
+ return r;
+ }
+ }
+ return saved_r;
+}
+
static struct kvm_callbacks qemu_kvm_ops = {
.debug = kvm_debug,
.inb = kvm_inb,
@@ -546,6 +614,31 @@ int kvm_qemu_init()
return 0;
}
+void do_setmemory(const char *value)
+{
+ int64_t target_ramsize;
+ char *ptr;
+
+ target_ramsize = strtoll(value, &ptr, 10);
+ switch (*ptr) {
+ case 'G': case 'g':
+ target_ramsize *= 1024;
+ case 'M': case 'm':
+ target_ramsize *= 1024;
+ case 'K': case 'k':
+ target_ramsize *= 1024;
+ default:
+ break;
+ }
+
+ if (target_ramsize > ram_size) {
+ term_printf("Invalid RAM size, maximum: %d\n", ram_size);
+ return;
+ }
+
+ balloon_update_target(target_ramsize);
+}
+
int kvm_qemu_create_context(void)
{
int r;
Index: kvm-userspace/qemu/qemu-kvm.h
===================================================================
--- kvm-userspace.orig/qemu/qemu-kvm.h
+++ kvm-userspace/qemu/qemu-kvm.h
@@ -39,6 +39,9 @@ void kvm_arch_post_kvm_run(void *opaque,
int kvm_arch_has_work(CPUState *env);
int kvm_arch_try_push_interrupts(void *opaque);
void kvm_arch_update_regs_for_sipi(CPUState *env);
+int kvm_handle_ballooning_call(void *data, size_t len);
+
+void do_setmemory(const char *value);
extern int kvm_allowed;
extern int kvm_irqchip;
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
reply other threads:[~2008-01-09 18:26 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080109182611.GD303@dmt \
--to=marcelo-bw31mazkks3ytjvyw6ydsg@public.gmane.org \
--cc=aliguori-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org \
--cc=kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.