From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
To: xen-devel@lists.xensource.com, keir.fraser@eu.citrix.com,
Ian.Jackson@eu.citrix.com, Ian.Campbell@citrix.com
Cc: konrad.wilk@oracle.com
Subject: [PATCH 5 of 6] xend/xc: Implement a domain_set_e820_hole function to be used by python code
Date: Sat, 24 Mar 2012 13:41:46 -0400 [thread overview]
Message-ID: <95eda76084314aa8a5cf.1332610906@phenom.dumpdata.com> (raw)
In-Reply-To: <patchbomb.1332610901@phenom.dumpdata.com>
# HG changeset patch
# User Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
# Date 1332610898 14400
# Node ID 95eda76084314aa8a5cfd4b5e83969823492deda
# Parent d42921da3931026ecf5da7c0e5bb86074e77cf71
xend/xc: Implement a domain_set_e820_hole function to be used by python code
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
diff -r d42921da3931 -r 95eda7608431 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Sat Mar 24 13:41:38 2012 -0400
+++ b/tools/python/xen/lowlevel/xc/xc.c Sat Mar 24 13:41:38 2012 -0400
@@ -16,6 +16,7 @@
#include <sys/mman.h>
#include <netdb.h>
#include <arpa/inet.h>
+#include <stdio.h>
#include "xenctrl.h"
#include <xen/elfnote.h>
@@ -1697,6 +1698,243 @@ static PyObject *pyxc_domain_set_memmap_
return zero;
}
+#ifdef PRIu64
+static const char *e820_names(int type)
+{
+ switch (type) {
+ case E820_RAM: return "RAM";
+ case E820_RESERVED: return "Reserved";
+ case E820_ACPI: return "ACPI";
+ case E820_NVS: return "ACPI NVS";
+ case E820_UNUSABLE: return "Unusable";
+ default: break;
+ }
+ return "Unknown";
+}
+#endif
+static int e820_sanitize(struct e820entry src[],
+ uint32_t *nr_entries,
+ unsigned long map_limitkb,
+ unsigned long balloon_kb)
+{
+ uint64_t delta_kb = 0, start = 0, start_kb = 0, last = 0, ram_end;
+ uint32_t i, idx = 0, nr;
+ struct e820entry e820[E820MAX];
+
+ if (!src || !map_limitkb || !balloon_kb || !nr_entries)
+ return -EINVAL;
+
+ nr = *nr_entries;
+ if (!nr)
+ return -EINVAL;
+
+ if (nr > E820MAX)
+ return -EINVAL;
+
+ /* Weed out anything under 1MB */
+ for (i = 0; i < nr; i++) {
+ if (src[i].addr > 0x100000)
+ continue;
+
+ src[i].type = 0;
+ src[i].size = 0;
+ src[i].addr = -1ULL;
+ }
+
+ /* Find the lowest and highest entry in E820, skipping over
+ * undesired entries. */
+ start = -1ULL;
+ last = 0;
+ for (i = 0; i < nr; i++) {
+ if ((src[i].type == E820_RAM) ||
+ (src[i].type == E820_UNUSABLE) ||
+ (src[i].type == 0))
+ continue;
+
+ start = src[i].addr < start ? src[i].addr : start;
+ last = src[i].addr + src[i].size > last ?
+ src[i].addr + src[i].size > last : last;
+ }
+ if (start > 1024)
+ start_kb = start >> 10;
+
+ /* Add the memory RAM region for the guest */
+ e820[idx].addr = 0;
+ e820[idx].size = (uint64_t)map_limitkb << 10;
+ e820[idx].type = E820_RAM;
+
+ /* .. and trim if neccessary */
+ if (start_kb && map_limitkb > start_kb) {
+ delta_kb = map_limitkb - start_kb;
+ if (delta_kb)
+ e820[idx].size -= (uint64_t)(delta_kb << 10);
+ }
+ /* Note: We don't touch balloon_kb here. Will add it at the end. */
+ ram_end = e820[idx].addr + e820[idx].size;
+ idx ++;
+#ifdef PRIu64
+ printf("Memory: %"PRIu64"kB End of RAM: " \
+ "0x%"PRIx64" (PFN) Delta: %"PRIu64"kB, PCI start: %"PRIu64"kB " \
+ "(0x%"PRIx64" PFN), Balloon %"PRIu64"kB\n", (uint64_t)map_limitkb,
+ ram_end >> 12, delta_kb, start_kb ,start >> 12,
+ (uint64_t)balloon_kb);
+#endif
+
+ /* This whole code below is to guard against if the Intel IGD is passed into
+ * the guest. If we don't pass in IGD, this whole code can be ignored.
+ *
+ * The reason for this code is that Intel boxes fill their E820 with
+ * E820_RAM amongst E820_RESERVED and we can't just ditch those E820_RAM.
+ * That is b/c any "gaps" in the E820 is considered PCI I/O space by
+ * Linux and it would be utilized by the Intel IGD as I/O space while
+ * in reality it was an RAM region.
+ *
+ * What this means is that we have to walk the E820 and for any region
+ * that is RAM and below 4GB and above ram_end, needs to change its type
+ * to E820_UNUSED. We also need to move some of the E820_RAM regions if
+ * the overlap with ram_end. */
+ for (i = 0; i < nr; i++) {
+ uint64_t end = src[i].addr + src[i].size;
+
+ /* We don't care about E820_UNUSABLE, but we need to
+ * change the type to zero b/c the loop after this
+ * sticks E820_UNUSABLE on the guest's E820 but ignores
+ * the ones with type zero. */
+ if ((src[i].type == E820_UNUSABLE) ||
+ /* Any region that is within the "RAM region" can
+ * be safely ditched. */
+ (end < ram_end)) {
+ src[i].type = 0;
+ continue;
+ }
+
+ /* Look only at RAM regions. */
+ if (src[i].type != E820_RAM)
+ continue;
+
+ /* We only care about RAM regions below 4GB. */
+ if (src[i].addr >= (1ULL<<32))
+ continue;
+
+ /* E820_RAM overlaps with our RAM region. Move it */
+ if (src[i].addr < ram_end) {
+ uint64_t delta;
+
+ src[i].type = E820_UNUSABLE;
+ delta = ram_end - src[i].addr;
+ /* The end < ram_end should weed this out */
+ if (src[i].size - delta < 0)
+ src[i].type = 0;
+ else {
+ src[i].size -= delta;
+ src[i].addr = ram_end;
+ }
+ if (src[i].addr + src[i].size != end) {
+ /* We messed up somewhere */
+ src[i].type = 0;
+#ifdef PRIu64
+ printf( "Computed E820 wrongly. Continuing on.");
+#endif
+ }
+ }
+ /* Lastly, convert the RAM to UNSUABLE. Look in the Linux kernel
+ at git commit 2f14ddc3a7146ea4cd5a3d1ecd993f85f2e4f948
+ "xen/setup: Inhibit resource API from using System RAM E820
+ gaps as PCI mem gaps" for full explanation. */
+ if (end > ram_end)
+ src[i].type = E820_UNUSABLE;
+ }
+
+ /* Check if there is a region between ram_end and start. */
+ if (start > ram_end) {
+ int add_unusable = 1;
+ for (i = 0; i < nr && add_unusable; i++) {
+ if (src[i].type != E820_UNUSABLE)
+ continue;
+ if (ram_end != src[i].addr)
+ continue;
+ if (start != src[i].addr + src[i].size) {
+ /* there is one, adjust it */
+ src[i].size = start - src[i].addr;
+ }
+ add_unusable = 0;
+ }
+ /* .. and if not present, add it in. This is to guard against
+ the Linux guest assuming that the gap between the end of
+ RAM region and the start of the E820_[ACPI,NVS,RESERVED]
+ is PCI I/O space. Which it certainly is _not_. */
+ if (add_unusable) {
+ e820[idx].type = E820_UNUSABLE;
+ e820[idx].addr = ram_end;
+ e820[idx].size = start - ram_end;
+ idx++;
+ }
+ }
+ /* Almost done: copy them over, ignoring the undesireable ones */
+ for (i = 0; i < nr; i++) {
+ if ((src[i].type == E820_RAM) ||
+ (src[i].type == 0))
+ continue;
+
+ e820[idx].type = src[i].type;
+ e820[idx].addr = src[i].addr;
+ e820[idx].size = src[i].size;
+ idx++;
+ }
+ /* At this point we have the mapped RAM + E820 entries from src. */
+ if (balloon_kb) {
+ /* and if we truncated the RAM region, then add it to the end. */
+ e820[idx].type = E820_RAM;
+ e820[idx].addr = (uint64_t)(1ULL << 32) > last ?
+ (uint64_t)(1ULL << 32) : last;
+ /* also add the balloon memory to the end. */
+ e820[idx].size = (uint64_t)(delta_kb << 10) +
+ (uint64_t)(balloon_kb << 10);
+ idx++;
+
+ }
+ nr = idx;
+#ifdef PRIu64
+ for (i = 0; i < nr; i++) {
+ printf(":\t[%"PRIx64" -> %"PRIx64"] %s",
+ e820[i].addr >> 12, (e820[i].addr + e820[i].size) >> 12,
+ e820_names(e820[i].type));
+ }
+#endif
+ /* Done: copy the sanitized version. */
+ *nr_entries = nr;
+ memcpy(src, e820, nr * sizeof(struct e820entry));
+ return 0;
+}
+
+static PyObject *pyxc_domain_set_e820_hole(XcObject *self, PyObject *args)
+{
+ uint32_t dom, nr;
+ unsigned int target_kb;
+ unsigned int balloon_kb;
+ int rc;
+ struct e820entry map[E820MAX];
+
+ if ( !PyArg_ParseTuple(args, "iii", &dom, &target_kb, &balloon_kb) )
+ return NULL;
+
+ rc = xc_get_machine_memory_map(self->xc_handle, map, E820MAX);
+ if (rc < 0)
+ return pyxc_error_to_exception(self->xc_handle);
+
+ nr = rc;
+ rc = e820_sanitize(map, &nr, target_kb, balloon_kb);
+ if (rc)
+ return pyxc_error_to_exception(self->xc_handle);
+
+ rc = xc_domain_set_memory_map(self->xc_handle, dom, map, nr);
+ if (rc < 0)
+ return pyxc_error_to_exception(self->xc_handle);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
static PyObject *pyxc_domain_ioport_permission(XcObject *self,
PyObject *args,
PyObject *kwds)
@@ -2701,6 +2939,15 @@ static PyMethodDef pyxc_methods[] = {
" map_limitkb [int]: .\n"
"Returns: [int] 0 on success; -1 on error.\n" },
+ { "domain_set_e820_hole",
+ (PyCFunction)pyxc_domain_set_e820_hole,
+ METH_VARARGS, "\n"
+ "Set a domain's E820 memory map\n"
+ " dom [int]: Identifier of domain.\n"
+ " target_memkb [int]: .\n"
+ " balloon_kb [int]: .\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
#ifdef __ia64__
{ "nvram_init",
(PyCFunction)pyxc_nvram_init,
next prev parent reply other threads:[~2012-03-24 17:41 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-24 17:41 [PATCH 0 of 6] Various patches - debug help, xend fixes and S3 resume fixes (v1) Konrad Rzeszutek Wilk
2012-03-24 17:41 ` [PATCH 1 of 6] linux-xencommons: Load xen-acpi-processor Konrad Rzeszutek Wilk
2012-03-27 13:39 ` Ian Jackson
2012-03-24 17:41 ` [PATCH 2 of 6] xen/vga: Add 'vga_delay' parameter to delay screen output by 2 second per screen output Konrad Rzeszutek Wilk
2012-03-26 8:43 ` Jan Beulich
2012-03-27 13:41 ` Ian Jackson
2012-03-24 17:41 ` [PATCH 3 of 6] xen/pat: After suspend re-write PAT if BIOS changed it Konrad Rzeszutek Wilk
2012-03-26 8:50 ` Jan Beulich
2012-04-02 15:28 ` Konrad Rzeszutek Wilk
2012-04-03 13:03 ` Tom Goetz
2012-03-24 17:41 ` [PATCH 4 of 6] xend: Don't crash due to weird PCI devices Konrad Rzeszutek Wilk
2012-03-27 13:39 ` Ian Jackson
2012-03-24 17:41 ` Konrad Rzeszutek Wilk [this message]
2012-03-26 9:42 ` [PATCH 5 of 6] xend/xc: Implement a domain_set_e820_hole function to be used by python code Ian Campbell
2012-04-02 15:59 ` Konrad Rzeszutek Wilk
2012-04-02 16:02 ` Ian Campbell
2012-03-24 17:41 ` [PATCH 6 of 6] xend: Add support for passing in the host's E820 for PCI passthrough Konrad Rzeszutek Wilk
2012-03-27 13:43 ` Ian Jackson
2012-04-02 16:00 ` Konrad Rzeszutek Wilk
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=95eda76084314aa8a5cf.1332610906@phenom.dumpdata.com \
--to=konrad.wilk@oracle.com \
--cc=Ian.Campbell@citrix.com \
--cc=Ian.Jackson@eu.citrix.com \
--cc=keir.fraser@eu.citrix.com \
--cc=xen-devel@lists.xensource.com \
/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.