aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndres Lagar-Cavilla <andres@lagarcavilla.org>2012-03-01 16:41:39 +0000
committerAndres Lagar-Cavilla <andres@lagarcavilla.org>2012-03-01 16:41:39 +0000
commitf140a8b192aa94dcd9356b558a12652b3c96d0f4 (patch)
tree927b0cd7ba972a338585b47255b426ef1fed9f33
parent9f06a2e65888fc0972c977f3f951f41c3d17f22b (diff)
downloadxen-f140a8b192aa94dcd9356b558a12652b3c96d0f4.tar.gz
xen-f140a8b192aa94dcd9356b558a12652b3c96d0f4.tar.bz2
xen-f140a8b192aa94dcd9356b558a12652b3c96d0f4.zip
Lowmemd: Simple demo code to show use of VIRQ_ENOMEM
Signed-off-by: Andres Lagar-Cavilla <andres@lagarcavilla.org> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
-rw-r--r--.hgignore1
-rw-r--r--tools/misc/Makefile7
-rw-r--r--tools/misc/xen-lowmemd.c148
3 files changed, 154 insertions, 2 deletions
diff --git a/.hgignore b/.hgignore
index 46655adff6..008e5fb27c 100644
--- a/.hgignore
+++ b/.hgignore
@@ -202,6 +202,7 @@
^tools/misc/xenperf$
^tools/misc/xenpm$
^tools/misc/xen-hvmctx$
+^tools/misc/xen-lowmemd$
^tools/misc/gtraceview$
^tools/misc/gtracestat$
^tools/misc/xenlockprof$
diff --git a/tools/misc/Makefile b/tools/misc/Makefile
index 817398bc9b..bd9b017ad2 100644
--- a/tools/misc/Makefile
+++ b/tools/misc/Makefile
@@ -9,7 +9,7 @@ CFLAGS += $(CFLAGS_xeninclude)
HDRS = $(wildcard *.h)
TARGETS-y := xenperf xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd
-TARGETS-$(CONFIG_X86) += xen-detect xen-hvmctx xen-hvmcrash
+TARGETS-$(CONFIG_X86) += xen-detect xen-hvmctx xen-hvmcrash xen-lowmemd
TARGETS-$(CONFIG_MIGRATE) += xen-hptool
TARGETS := $(TARGETS-y)
@@ -21,7 +21,7 @@ INSTALL_BIN-y := xencons
INSTALL_BIN-$(CONFIG_X86) += xen-detect
INSTALL_BIN := $(INSTALL_BIN-y)
-INSTALL_SBIN-y := xm xen-bugtool xen-python-path xend xenperf xsview xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd xen-ringwatch
+INSTALL_SBIN-y := xm xen-bugtool xen-python-path xend xenperf xsview xenpm xen-tmem-list-parse gtraceview gtracestat xenlockprof xenwatchdogd xen-ringwatch xen-lowmemd
INSTALL_SBIN-$(CONFIG_X86) += xen-hvmctx xen-hvmcrash
INSTALL_SBIN-$(CONFIG_MIGRATE) += xen-hptool
INSTALL_SBIN := $(INSTALL_SBIN-y)
@@ -70,6 +70,9 @@ xen-hptool: xen-hptool.o
xenwatchdogd: xenwatchdogd.o
$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
+xen-lowmemd: xen-lowmemd.o
+ $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS)
+
gtraceview: gtraceview.o
$(CC) $(LDFLAGS) -o $@ $< $(CURSES_LIBS) $(APPEND_LDFLAGS)
diff --git a/tools/misc/xen-lowmemd.c b/tools/misc/xen-lowmemd.c
new file mode 100644
index 0000000000..42098e4d6f
--- /dev/null
+++ b/tools/misc/xen-lowmemd.c
@@ -0,0 +1,148 @@
+/*
+ * xen-lowmemd: demo VIRQ_ENOMEM
+ * Andres Lagar-Cavilla (GridCentric Inc.)
+ */
+
+#include <stdio.h>
+#include <xenctrl.h>
+#include <xs.h>
+#include <stdlib.h>
+#include <string.h>
+
+static evtchn_port_t virq_port = -1;
+static xc_evtchn *xce_handle = NULL;
+static xc_interface *xch = NULL;
+static struct xs_handle *xs_handle = NULL;
+
+void cleanup(void)
+{
+ if (virq_port > -1)
+ xc_evtchn_unbind(xce_handle, virq_port);
+ if (xce_handle)
+ xc_evtchn_close(xce_handle);
+ if (xch)
+ xc_interface_close(xch);
+ if (xs_handle)
+ xs_daemon_close(xs_handle);
+}
+
+/* Never shrink dom0 below 1 GiB */
+#define DOM0_FLOOR (1 << 30)
+#define DOM0_FLOOR_PG ((DOM0_FLOOR) >> 12)
+
+/* Act if free memory is less than 92 MiB */
+#define THRESHOLD (92 << 20)
+#define THRESHOLD_PG ((THRESHOLD) >> 12)
+
+#define BUFSZ 512
+void handle_low_mem(void)
+{
+ xc_dominfo_t dom0_info;
+ xc_physinfo_t info;
+ unsigned long long free_pages, dom0_pages, diff, dom0_target;
+ char data[BUFSZ], error[BUFSZ];
+
+ if (xc_physinfo(xch, &info) < 0)
+ {
+ perror("Getting physinfo failed");
+ return;
+ }
+
+ free_pages = (unsigned long long) info.free_pages;
+ printf("Available free pages: 0x%llx:%llux\n",
+ free_pages, free_pages);
+
+ /* Don't do anything if we have more than the threshold free */
+ if ( free_pages >= THRESHOLD_PG )
+ return;
+ diff = THRESHOLD_PG - free_pages;
+
+ if (xc_domain_getinfo(xch, 0, 1, &dom0_info) < 1)
+ {
+ perror("Failed to get dom0 info");
+ return;
+ }
+
+ dom0_pages = (unsigned long long) dom0_info.nr_pages;
+ printf("Dom0 pages: 0x%llx:%llu\n", dom0_pages, dom0_pages);
+ dom0_target = dom0_pages - diff;
+ if (dom0_target <= DOM0_FLOOR_PG)
+ return;
+
+ printf("Shooting for dom0 target 0x%llx:%llu\n",
+ dom0_target, dom0_target);
+
+ snprintf(data, BUFSZ, "%llu", dom0_target);
+ if (!xs_write(xs_handle, XBT_NULL,
+ "/local/domain/0/memory/target", data, strlen(data)))
+ {
+ snprintf(error, BUFSZ,"Failed to write target %s to xenstore", data);
+ perror(error);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int rc;
+
+ atexit(cleanup);
+
+ xch = xc_interface_open(NULL, NULL, 0);
+ if (xch == NULL)
+ {
+ perror("Failed to open xc interface");
+ return 1;
+ }
+
+ xce_handle = xc_evtchn_open(NULL, 0);
+ if (xce_handle == NULL)
+ {
+ perror("Failed to open evtchn device");
+ return 2;
+ }
+
+ xs_handle = xs_daemon_open();
+ if (xs_handle == NULL)
+ {
+ perror("Failed to open xenstore connection");
+ return 3;
+ }
+
+ if ((rc = xc_evtchn_bind_virq(xce_handle, VIRQ_ENOMEM)) == -1)
+ {
+ perror("Failed to bind to domain exception virq port");
+ return 4;
+ }
+
+ virq_port = rc;
+
+ while(1)
+ {
+ evtchn_port_t port;
+
+ if ((port = xc_evtchn_pending(xce_handle)) == -1)
+ {
+ perror("Failed to listen for pending event channel");
+ return 5;
+ }
+
+ if (port != virq_port)
+ {
+ char data[BUFSZ];
+ snprintf(data, BUFSZ, "Wrong port, got %d expected %d", port, virq_port);
+ perror(data);
+ return 6;
+ }
+
+ if (xc_evtchn_unmask(xce_handle, port) == -1)
+ {
+ perror("Failed to unmask port");
+ return 7;
+ }
+
+ printf("Got a virq kick, time to get work\n");
+ handle_low_mem();
+ }
+
+ return 0;
+}