WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [RFC Patch] Support for making an E820 PCI hole in toolstack

To: xen-devel@xxxxxxxxxxxxxxxxxxx, stefano.stabellini@xxxxxxxxxxxxx, gianni.tedesco@xxxxxxxxxx
Subject: [Xen-devel] [RFC Patch] Support for making an E820 PCI hole in toolstack (xl + xm)
From: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
Date: Fri, 12 Nov 2010 18:08:55 -0500
Cc: Jeremy Fitzhardinge <jeremy@xxxxxxxx>, bruce.edge@xxxxxxxxx
Delivery-date: Fri, 12 Nov 2010 15:10:33 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.20 (2009-06-14)
Hey guys,

Attached is an RFC patch for making a PCI hole in the PV guests. This allows
PV guests(*) with 4GB or more to now properly work with or without
PCI passthrough cards.

Previously the Linux kernel would not be able to allocate the PCI region
underneath the 4GB region as that region was all System RAM. And you would see
this:

[    0.000000] PM: Registered nosave memory: 00000000000a0000 - 0000000000100000
[    0.000000] PCI: Warning: Cannot find a gap in the 32bit address range
[    0.000000] PCI: Unassigned devices with 32bit resource registers may break!
[    0.000000] Allocating PCI resources starting at 100100000 (gap: 
100100000:400000)


This patchset punches an PCI hole in the E820 region and as well fills the P2M 
properly,
so that now you can see (*):
[    0.000000] Allocating PCI resources starting at a0000000 (gap: 
a0000000:60000000)

It adds a new option to guest config file, which is "pci_hole". The user can
specify the PFN number, such as '0xc0000' or in case of using the xl, '1' which
will automatically figure out the start of the PCI address.

*: This option requires support in the Linux kernel to actually deal with two 
entries in the E820 map and P2M space filled with ~0. 


The patches (draft, not ready for upstream) for the Linux kernel to support 
this are
available at:

git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen.git devel/e820-hole

All of these patches make the E820 of the Linux guest with 4GB (or more) passed
look like this (2.6.37-rc1+devel/e820-hole):
[    0.000000]  Xen: 0000000000000000 - 00000000000a0000 (usable)
[    0.000000]  Xen: 00000000000a0000 - 0000000000100000 (reserved)
[    0.000000]  Xen: 0000000000100000 - 00000000a0000000 (usable)
[    0.000000]  Xen: 0000000100000000 - 0000000160800000 (usable)

compared to (2.6.36)
[    0.000000]  Xen: 0000000000000000 - 00000000000a0000 (usable)
[    0.000000]  Xen: 00000000000a0000 - 0000000000100000 (reserved)
[    0.000000]  Xen: 0000000000100000 - 0000000100000000 (usable)

and (2.6.37-rc1):
[    0.000000]  Xen: 0000000000000000 - 00000000000a0000 (usable)
[    0.000000]  Xen: 00000000000a0000 - 0000000000100000 (reserved)
[    0.000000]  Xen: 0000000000100000 - 0000000100800000 (usable)

In regards to the patches that I am attaching here, what is the magic 
incantention
to make the indentation/StyleGuide proper for the tools/libxc directory? The 
tab spacing
is off a bit (I think).

I've tested this so far only on 64-bit guests, and I am quite sure the 
tool-stack
needs some extra care for the 32-bit guests..

But please take a look and give feedback.

diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
--- a/tools/libxc/xc_dom.h
+++ b/tools/libxc/xc_dom.h
@@ -91,6 +91,8 @@ struct xc_dom_image {
 
     /* physical memory */
     xen_pfn_t total_pages;
+    /* start of the pci_hole. goes up to 4gb */
+    xen_pfn_t pci_hole;
     struct xc_dom_phys *phys_pages;
     int realmodearea_log;
 
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
--- a/tools/libxc/xc_dom_core.c
+++ b/tools/libxc/xc_dom_core.c
@@ -715,17 +715,22 @@ int xc_dom_update_guest_p2m(struct xc_do
     uint32_t *p2m_32;
     uint64_t *p2m_64;
     xen_pfn_t i;
+    size_t tot_pages;
 
     if ( !dom->p2m_guest )
         return 0;
 
+    tot_pages = dom->total_pages;
+    if (dom->pci_hole)
+         tot_pages += (0x100000 - dom->pci_hole);
+
     switch ( dom->arch_hooks->sizeof_pfn )
     {
     case 4:
         DOMPRINTF("%s: dst 32bit, pages 0x%" PRIpfn "",
-                  __FUNCTION__, dom->total_pages);
+                  __FUNCTION__, tot_pages);
         p2m_32 = dom->p2m_guest;
-        for ( i = 0; i < dom->total_pages; i++ )
+        for ( i = 0; i < tot_pages; i++ )
             if ( dom->p2m_host[i] != INVALID_P2M_ENTRY )
                 p2m_32[i] = dom->p2m_host[i];
             else
@@ -733,9 +738,9 @@ int xc_dom_update_guest_p2m(struct xc_do
         break;
     case 8:
         DOMPRINTF("%s: dst 64bit, pages 0x%" PRIpfn "",
-                  __FUNCTION__, dom->total_pages);
+                  __FUNCTION__, tot_pages);
         p2m_64 = dom->p2m_guest;
-        for ( i = 0; i < dom->total_pages; i++ )
+        for ( i = 0; i < tot_pages; i++ )
             if ( dom->p2m_host[i] != INVALID_P2M_ENTRY )
                 p2m_64[i] = dom->p2m_host[i];
             else
diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
--- a/tools/libxc/xc_dom_x86.c
+++ b/tools/libxc/xc_dom_x86.c
@@ -406,6 +406,15 @@ static int alloc_magic_pages(struct xc_d
 {
     size_t p2m_size = dom->total_pages * dom->arch_hooks->sizeof_pfn;
 
+    if (dom->pci_hole && (dom->total_pages > dom->pci_hole))
+    {
+       size_t p2m_pci_hole_size = (0x100000 - dom->pci_hole) *
+                                 dom->arch_hooks->sizeof_pfn;
+
+        DOMPRINTF("%s: Expanding P2M to include PCI hole (%ld->%ld)\n",
+               __FUNCTION__, p2m_size, p2m_size + p2m_pci_hole_size);
+       p2m_size += p2m_pci_hole_size;
+    }
     /* allocate phys2mach table */
     if ( xc_dom_alloc_segment(dom, &dom->p2m_seg, "phys2mach", 0, p2m_size) )
         return -1;
@@ -712,6 +721,7 @@ int arch_setup_meminit(struct xc_dom_ima
 {
     int rc;
     xen_pfn_t pfn, allocsz, i, j, mfn;
+    size_t p2m_size;
 
     rc = x86_compat(dom->xch, dom->guest_domid, dom->guest_type);
     if ( rc )
@@ -723,8 +733,13 @@ int arch_setup_meminit(struct xc_dom_ima
         if ( rc )
             return rc;
     }
+    p2m_size = dom->total_pages;
 
-    dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * dom->total_pages);
+    if (dom->pci_hole && (dom->total_pages > dom->pci_hole))
+               p2m_size += (0x100000 - dom->pci_hole);
+
+    DOMPRINTF("Allocating %ld bytes for P2M", p2m_size * sizeof(xen_pfn_t));
+    dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * p2m_size);
     if ( dom->superpages )
     {
         int count = dom->total_pages >> SUPERPAGE_PFN_SHIFT;
@@ -750,21 +765,66 @@ int arch_setup_meminit(struct xc_dom_ima
     }
     else
     {
-        /* setup initial p2m */
-        for ( pfn = 0; pfn < dom->total_pages; pfn++ )
-            dom->p2m_host[pfn] = pfn;
-        
-        /* allocate guest memory */
-        for ( i = rc = allocsz = 0;
-              (i < dom->total_pages) && !rc;
-              i += allocsz )
+       /* for PCI mapping, stick INVALID_MFN in the PCI_HOLE */
+        if ( dom->pci_hole && (dom->total_pages > dom->pci_hole) )
         {
-            allocsz = dom->total_pages - i;
-            if ( allocsz > 1024*1024 )
-                allocsz = 1024*1024;
-            rc = xc_domain_populate_physmap_exact(
-                dom->xch, dom->guest_domid, allocsz,
-                0, 0, &dom->p2m_host[i]);
+            /* setup initial p2m in three passes. */
+            for (pfn = 0; pfn < dom->pci_hole; pfn++)
+              dom->p2m_host[pfn] = pfn;
+
+            xc_dom_printf (dom->xch, "%s: 0x0->0x%lx has PFNs.", __FUNCTION__, 
pfn);
+            xc_dom_printf (dom->xch, "%s: 0x%lx -> 0x%x has INVALID_MFN",
+                          __FUNCTION__, pfn, 0x100000);
+            for (; pfn < 0x100000; pfn++)
+              dom->p2m_host[pfn] = INVALID_MFN;
+
+            for (; pfn < 0x100000 + dom->total_pages - dom->pci_hole; pfn++)
+              dom->p2m_host[pfn] = pfn;
+            xc_dom_printf (dom->xch, "%s: 0x%x -> 0x%lx has PFNs.", 
__FUNCTION__,
+                           0x100000, pfn);
+
+            /* allocate guest memory in two passes. */
+            for (i = rc = allocsz = 0; (i < dom->pci_hole) && !rc; i += 
allocsz)
+            {
+              allocsz = dom->pci_hole - i;
+              xc_dom_printf (dom->xch, "%s: Populating M2P 0x%lx->0x%lx",
+                             __FUNCTION__, i, i + allocsz);
+              rc = xc_domain_populate_physmap_exact (dom->xch, 
dom->guest_domid,
+                                 allocsz, 0, 0,
+                                 &dom->p2m_host[i]);
+            }
+            for (i = 0x100000, allocsz = rc = 0;
+                 (i < (0x100000 + dom->total_pages - dom->pci_hole))
+                  && !rc; i += allocsz)
+            {
+              allocsz = (dom->total_pages - dom->pci_hole) - (i - 0x100000);
+              if (allocsz > 1024 * 1024)
+                allocsz = 1024 * 1024;
+              xc_dom_printf (dom->xch, "%s: Populating M2P 0x%lx->0x%lx",
+                             __FUNCTION__, i, i + allocsz);
+              rc = xc_domain_populate_physmap_exact (dom->xch, 
dom->guest_domid,
+                                                      allocsz, 0, 0,
+                                                      &dom->p2m_host[i]);
+            }
+            xc_dom_printf (dom->xch, "%s: Done with PCI populate physmap",
+                          __FUNCTION__);
+        } else {
+                /* setup initial p2m */
+                for ( pfn = 0; pfn < dom->total_pages; pfn++ )
+                    dom->p2m_host[pfn] = pfn;
+                
+                /* allocate guest memory */
+                for ( i = rc = allocsz = 0;
+                      (i < dom->total_pages) && !rc;
+                      i += allocsz )
+                {
+                    allocsz = dom->total_pages - i;
+                    if ( allocsz > 1024*1024 )
+                        allocsz = 1024*1024;
+                    rc = xc_domain_populate_physmap_exact(
+                        dom->xch, dom->guest_domid, allocsz,
+                        0, 0, &dom->p2m_host[i]);
+                }
         }
     }
 
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -481,16 +481,25 @@ int xc_domain_pin_memory_cacheattr(xc_in
 #include "xc_e820.h"
 int xc_domain_set_memmap_limit(xc_interface *xch,
                                uint32_t domid,
-                               unsigned long map_limitkb)
+                               unsigned long map_limitkb,
+                               xen_pfn_t pci_hole_start)
 {
     int rc;
+    uint64_t delta_kb;
+    size_t e820_sz;
     struct xen_foreign_memory_map fmap = {
         .domid = domid,
         .map = { .nr_entries = 1 }
     };
     DECLARE_HYPERCALL_BUFFER(struct e820entry, e820);
 
-    e820 = xc_hypercall_buffer_alloc(xch, e820, sizeof(*e820));
+    delta_kb = map_limitkb - (uint64_t)(pci_hole_start << 2);
+    if (pci_hole_start && (delta_kb > 0))
+      e820_sz = sizeof(*e820);
+    else
+      e820_sz = sizeof(*e820)*2;
+
+    e820 = xc_hypercall_buffer_alloc(xch, e820, e820_sz);
 
     if ( e820 == NULL )
     {
@@ -502,6 +511,16 @@ int xc_domain_set_memmap_limit(xc_interf
     e820->size = (uint64_t)map_limitkb << 10;
     e820->type = E820_RAM;
 
+    if (pci_hole_start && (delta_kb > 0))
+    {
+       fmap.map.nr_entries ++;
+       e820[0].size = (uint64_t)pci_hole_start << 12;
+ 
+       e820[1].type = E820_RAM;
+       e820[1].addr = (uint64_t)0x100000 << 12; /* val in pfn...  */
+       e820[1].size = (uint64_t)delta_kb << 10; /* .. while here in in kB. */
+    }
+
     set_xen_guest_handle(fmap.map.buffer, e820);
 
     rc = do_memory_op(xch, XENMEM_set_memory_map, &fmap, sizeof(fmap));
@@ -513,7 +532,8 @@ int xc_domain_set_memmap_limit(xc_interf
 #else
 int xc_domain_set_memmap_limit(xc_interface *xch,
                                uint32_t domid,
-                               unsigned long map_limitkb)
+                               unsigned long map_limitkb,
+                               xen_pfn_t pci_hole_start)
 {
     PERROR("Function not implemented");
     errno = ENOSYS;
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -913,7 +913,8 @@ int xc_domain_setmaxmem(xc_interface *xc
 
 int xc_domain_set_memmap_limit(xc_interface *xch,
                                uint32_t domid,
-                               unsigned long map_limitkb);
+                               unsigned long map_limitkb,
+                               xen_pfn_t pci_hole_start);
 
 int xc_domain_set_time_offset(xc_interface *xch,
                               uint32_t domid,
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -392,6 +392,7 @@ int libxl_device_disk_getinfo(libxl_ctx 
                               libxl_device_disk *disk, libxl_diskinfo 
*diskinfo);
 int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk 
*disk);
 
+int libxl_find_pci_hole(uint32_t *start_pfn);
 /*
  * Make a disk available in this domain. Returns path to a device.
  */
diff --git a/tools/libxl/libxl.idl b/tools/libxl/libxl.idl
--- a/tools/libxl/libxl.idl
+++ b/tools/libxl/libxl.idl
@@ -110,6 +110,7 @@ libxl_domain_build_info = Struct("domain
                                         ])),
                  ("pv", "!%s", Struct(None,
                                        [("slack_memkb", uint32),
+                                        ("pci_hole_start", uint32),
                                         ("bootloader", string),
                                         ("bootloader_args", string),
                                         ("cmdline", string),
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -71,7 +71,8 @@ int libxl__build_pre(libxl_ctx *ctx, uin
     xc_domain_setmaxmem(ctx->xch, domid, info->target_memkb + 
LIBXL_MAXMEM_CONSTANT);
     xc_domain_set_memmap_limit(ctx->xch, domid, 
             (info->hvm) ? info->max_memkb : 
-            (info->max_memkb + info->u.pv.slack_memkb));
+            (info->max_memkb + info->u.pv.slack_memkb),
+            (info->hvm) ? 0 : info->u.pv.pci_hole_start);
     xc_domain_set_tsc_info(ctx->xch, domid, info->tsc_mode, 0, 0, 0);
     if ( info->disable_migrate )
         xc_domain_disable_migrate(ctx->xch, domid);
@@ -181,6 +182,8 @@ int libxl__build_pv(libxl_ctx *ctx, uint
             }
         }
     }
+    if ( info->u.pv.pci_hole_start)
+        dom->pci_hole = info->u.pv.pci_hole_start;
 
     dom->flags = flags;
     dom->console_evtchn = state->console_port;
diff --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c
--- a/tools/libxl/libxl_pci.c
+++ b/tools/libxl/libxl_pci.c
@@ -1066,3 +1066,51 @@ int libxl_device_pci_shutdown(libxl_ctx 
     free(pcidevs);
     return 0;
 }
+
+#define MAX_LINE 300
+int libxl_find_pci_hole(uint32_t *start_pfn)
+{
+       FILE *fp;
+       char *s;
+       char buf[MAX_LINE];
+       int ret = -ENODEV;
+       long int pci_hole_phys;
+
+       *start_pfn = 0;
+       fp = fopen("/proc/iomem", "r");
+       if (!fp)
+               return ret;
+
+       while (1) {
+               s = fgets(buf, MAX_LINE, fp);
+               if (!s)
+                       break;
+               if (strlen(buf) < 1)
+                       continue;
+               if (buf[strlen(buf)-1] == '\n')
+                       buf[strlen(buf)-1] = '\0';
+               s = strchr(buf,'P');
+               if (!s)
+                       continue;
+               if (strncmp(s, "PCI", 3) == 0) {
+                       if (buf[0] == ' ')
+                               continue;
+                       s = strchr(buf,'-');
+                       if (!s)
+                               break;
+                       s[0]='\0';
+                       pci_hole_phys = strtol(buf, NULL, 16);
+                       if (!pci_hole_phys)
+                               break;
+                       /* We don't want to the holes below 16MB. */
+                       if (pci_hole_phys <= 0x1000)
+                               continue;
+                       *start_pfn = pci_hole_phys >> 12;
+                       fprintf(stderr,"The value is 0x%d\n", *start_pfn);
+                       ret = 0;
+                       break;
+               }
+       }
+       fclose(fp);
+       return ret;
+}
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1078,6 +1078,14 @@ skip_vfb:
     if (!xlu_cfg_get_long (config, "pci_power_mgmt", &l))
         pci_power_mgmt = l;
 
+    if (!xlu_cfg_get_long (config, "pci_hole", &l)) {
+       if (l == 1) {
+          uint32_t pfn_start = 0;
+          if (!libxl_find_pci_hole(&pfn_start))
+               b_info->u.pv.pci_hole_start = pfn_start;
+       } else
+           b_info->u.pv.pci_hole_start = l;
+    }
     if (!xlu_cfg_get_list (config, "pci", &pcis, 0, 0)) {
         int i;
         d_config->num_pcidevs = 0;
diff --git a/tools/python/xen/lowlevel/xc/xc.c 
b/tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -458,6 +458,7 @@ static PyObject *pyxc_linux_build(XcObje
     unsigned int mem_mb;
     unsigned long store_mfn = 0;
     unsigned long console_mfn = 0;
+    unsigned long pci_hole_start = 0;
     PyObject* elfnote_dict;
     PyObject* elfnote = NULL;
     PyObject* ret;
@@ -467,14 +468,16 @@ static PyObject *pyxc_linux_build(XcObje
                                 "console_evtchn", "image",
                                 /* optional */
                                 "ramdisk", "cmdline", "flags",
-                                "features", "vhpt", "superpages", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiis|ssisii", kwd_list,
+                                "features", "vhpt", "superpages",
+                                "pci_hole", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiis|ssisiii", kwd_list,
                                       &domid, &store_evtchn, &mem_mb,
                                       &console_evtchn, &image,
                                       /* optional */
                                       &ramdisk, &cmdline, &flags,
-                                      &features, &vhpt, &superpages) )
+                                      &features, &vhpt, &superpages,
+                                      &pci_hole_start) )
         return NULL;
 
     xc_dom_loginit(self->xc_handle);
@@ -486,6 +489,8 @@ static PyObject *pyxc_linux_build(XcObje
 
     dom->superpages = superpages;
 
+    dom->pci_hole = pci_hole_start;
+
     if ( xc_dom_linux_build(self->xc_handle, dom, domid, mem_mb, image,
                             ramdisk, flags, store_evtchn, &store_mfn,
                             console_evtchn, &console_mfn) != 0 ) {
@@ -1659,11 +1664,13 @@ static PyObject *pyxc_domain_set_memmap_
 {
     uint32_t dom;
     unsigned int maplimit_kb;
-
-    if ( !PyArg_ParseTuple(args, "ii", &dom, &maplimit_kb) )
+    unsigned long pci_hole_start = 0;
+
+    if ( !PyArg_ParseTuple(args, "ii|i", &dom, &maplimit_kb, &pci_hole_start) )
         return NULL;
 
-    if ( xc_domain_set_memmap_limit(self->xc_handle, dom, maplimit_kb) != 0 )
+    if ( xc_domain_set_memmap_limit(self->xc_handle, dom, maplimit_kb,
+                                    pci_hole_start) != 0 )
         return pyxc_error_to_exception(self->xc_handle);
     
     Py_INCREF(zero);
@@ -2661,6 +2668,7 @@ static PyMethodDef pyxc_methods[] = {
       "Set a domain's physical memory mappping limit\n"
       " dom [int]: Identifier of domain.\n"
       " map_limitkb [int]: .\n"
+      " pci_hole_start [int]: PFN for start of PCI hole (optional).\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
 
 #ifdef __ia64__
diff --git a/tools/python/xen/xend/XendConfig.py 
b/tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py
+++ b/tools/python/xen/xend/XendConfig.py
@@ -241,6 +241,7 @@ XENAPI_CFG_TYPES = {
     'suppress_spurious_page_faults': bool0,
     's3_integrity' : int,
     'superpages' : int,
+    'pci_hole' : int,
     'memory_sharing': int,
     'pool_name' : str,
     'Description': str,
@@ -422,6 +423,7 @@ class XendConfig(dict):
             'target': 0,
             'pool_name' : 'Pool-0',
             'superpages': 0,
+            'pci_hole': 0,
             'description': '',
         }
         
@@ -2135,6 +2137,9 @@ class XendConfig(dict):
             image.append(['args', self['PV_args']])
         if self.has_key('superpages'):
             image.append(['superpages', self['superpages']])
+        if self.has_key('pci_hole'):
+            image.append(['pci_hole', self['pci_hole']])
+
 
         for key in XENAPI_PLATFORM_CFG_TYPES.keys():
             if key in self['platform']:
@@ -2179,6 +2184,10 @@ class XendConfig(dict):
         val = sxp.child_value(image_sxp, 'superpages')
         if val is not None:
             self['superpages'] = val
+
+        val = sxp.child_value(image_sxp, 'pci_hole')
+        if val is not None:
+            self['pci_hole'] = val
         
         val = sxp.child_value(image_sxp, 'memory_sharing')
         if val is not None:
diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py
+++ b/tools/python/xen/xend/image.py
@@ -84,6 +84,7 @@ class ImageHandler:
 
     ostype = None
     superpages = 0
+    pci_hole = 0
     memory_sharing = 0
 
     def __init__(self, vm, vmConfig):
@@ -711,6 +712,7 @@ class LinuxImageHandler(ImageHandler):
         self.vramsize = int(vmConfig['platform'].get('videoram',4)) * 1024
         self.is_stubdom = (self.kernel.find('stubdom') >= 0)
         self.superpages = int(vmConfig['superpages'])
+        self.pci_hole = int(vmConfig['pci_hole'])
 
     def buildDomain(self):
         store_evtchn = self.vm.getStorePort()
@@ -729,6 +731,7 @@ class LinuxImageHandler(ImageHandler):
         log.debug("features       = %s", self.vm.getFeatures())
         log.debug("flags          = %d", self.flags)
         log.debug("superpages     = %d", self.superpages)
+        log.debug("pci_hole       = %d", self.pci_hole)
         if arch.type == "ia64":
             log.debug("vhpt          = %d", self.vhpt)
 
@@ -742,7 +745,8 @@ class LinuxImageHandler(ImageHandler):
                               features       = self.vm.getFeatures(),
                               flags          = self.flags,
                               vhpt           = self.vhpt,
-                              superpages     = self.superpages)
+                              superpages     = self.superpages,
+                              pci_hole       = self.pci_hole)
 
     def getBitSize(self):
         return xc.getBitSize(image    = self.kernel,
@@ -774,7 +778,6 @@ class LinuxImageHandler(ImageHandler):
         args = args + ([ "-M", "xenpv"])
         return args
 
-
 class HVMImageHandler(ImageHandler):
 
     ostype = "hvm"
@@ -1065,7 +1068,7 @@ class X86_Linux_ImageHandler(LinuxImageH
         # set physical mapping limit
         # add an 8MB slack to balance backend allocations.
         mem_kb = self.getRequiredMaximumReservation() + (8 * 1024)
-        xc.domain_set_memmap_limit(self.vm.getDomid(), mem_kb)
+        xc.domain_set_memmap_limit(self.vm.getDomid(), mem_kb, self.pci_hole)
         rc = LinuxImageHandler.buildDomain(self)
         self.setCpuid()
         return rc
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py
+++ b/tools/python/xen/xm/create.py
@@ -680,6 +680,11 @@ gopts.var('superpages', val='0|1',
            fn=set_int, default=0,
            use="Create domain with superpages")
 
+gopts.var('pci_hole', val='0x<XXX>|0',
+           fn=set_int, default=0,
+           use="""Create domain with a PCI hole. The value is the PFN of the
+           start of PCI hole. Usually that is 0xc0000.""")
+
 def err(msg):
     """Print an error to stderr and exit.
     """
@@ -770,6 +775,9 @@ def configure_image(vals):
         config_image.append(['args', vals.extra])
     if vals.superpages:
         config_image.append(['superpages', vals.superpages])
+    if vals.pci_hole:
+        config_image.append(['pci_hole', vals.pci_hole])
+
 
     if vals.builder == 'hvm':
         configure_hvm(config_image, vals) 
diff --git a/tools/python/xen/xm/xenapi_create.py 
b/tools/python/xen/xm/xenapi_create.py
--- a/tools/python/xen/xm/xenapi_create.py
+++ b/tools/python/xen/xm/xenapi_create.py
@@ -285,6 +285,8 @@ class xenapi_create:
                 vm.attributes["s3_integrity"].value,
             "superpages":
                 vm.attributes["superpages"].value,
+            "pci_hole":
+                vm.attributes["pci_hole"].value,
             "memory_static_max":
                 get_child_node_attribute(vm, "memory", "static_max"),
             "memory_static_min":
@@ -697,6 +699,8 @@ class sxp2xml:
             = str(get_child_by_name(config, "s3_integrity", 0))
         vm.attributes["superpages"] \
             = str(get_child_by_name(config, "superpages", 0))
+        vm.attributes["pci_hole"] \
+            = str(get_child_by_name(config, "pci_hole", 0))
         vm.attributes["pool_name"] \
             = str(get_child_by_name(config, "pool_name", "Pool-0"))
 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel