Patches for PCI passthrough with modified E820 (v3).
PATCH 1/1 Patches for PCI passthrough with modified E820 (v3).
Hello,
This set of v3 patches allows a PV domain to see the machine's E820 and figure out where the "PCI I/O" gap is and match it with the reality.
Changelog since v2 posting:
- Moved 'libxl__e820_alloc' to be called from do_domain_create and if machine_e820 == true.
- Made no_machine_e820 be set to true, if the guest has no PCI devices (and is PV)
- Used Keir's re-worked code for E820 creation.
Changelog since v1 posting:
- Squashed the "x86: make the pv-only e820 array be dynamic" and "x86: adjust the size of the e820 for pv guest to be dynamic" together.
- Made xc_domain_set_memmap_limit use the 'xc_domain_set_memory_map'
- Moved 'libxl_e820_alloc' and 'libxl_e820_sanitize' to be an internal operation and called from 'libxl_device_pci_parse_bdf'.
- Expanded 'libxl_device_pci_parse_bdf' API call to have an extra argument (optional).
The short end is that with these patches a PV domain can:
- Use the correct PCI I/O gap. Before these patches, Linux guest would boot up and would tell:
[ 0.000000] Allocating PCI resources starting at 40000000 (gap: 40000000:c0000000) while in actuality the PCI I/O gap should have been: [ 0.000000] Allocating PCI resources starting at b0000000 (gap: b0000000:4c000000)
- The PV domain with PCI devices was limited to 3GB. It now can be booted with 4GB, 8GB, or whatever number you want. The PCI devices will now _not_ conflict with System RAM. Meaning the drivers can load.
- With 2.6.39 kernels (which has the 1-1 mapping code), the VM_IO flag will be now automatically applied to regions that are considerd PCI I/O regions. You can find out which those are by looking for '1-1' in the kernel bootup.
To use this patchset, the guest config file has to have the parameter 'pci=['<BDF>',...]' enabled.
This has been tested with 2.6.18 (RHEL5), 2.6.27(SLES11), 2.6.36, 2.6.37, 2.6.38, and 2.6.39 kernels. Also tested with PV NetBSD 5.1.
Tested this with the PCI devices (NIC, MSI), and with 2GB, 4GB, and 6GB guests with success.
P.S.
*There is a bug in the Linux kernel so that if you want to save/restore a PV guest that has 1-1 mapping it won't restore. Will post the patches shortly for that.
tools/libxc/xc_domain.c | 77 +++++++++----- tools/libxc/xc_e820.h | 3 tools/libxc/xenctrl.h | 11 ++ tools/libxl/libxl.idl | 1 tools/libxl/libxl_create.c | 8 + tools/libxl/libxl_internal.h | 1 tools/libxl/libxl_pci.c | 230 +++++++++++++++++++++++++++++++++++++++++++ tools/libxl/xl_cmdimpl.c | 3 xen/arch/x86/domain.c | 4 xen/arch/x86/mm.c | 44 ++++++-- xen/include/asm-x86/domain.h | 3 11 files changed, 351 insertions(+), 34 deletions(-)
PATCH 1/1 tools: Add xc_domain_set_memory_map and xc_get_machine_memory_map calls (x86, amd64 only)
# HG changeset patch
# User Konrad Rzeszutek Wilk <[email protected]>
# Date 1302633965 14400
# Node ID 6c05be60fbc74f5d3c751a379ce5c4a147e34132
# Parent 697ac895c11c6d5d82524de56796cee98fded2a5
tools: Add xc_domain_set_memory_map and xc_get_machine_memory_map calls (x86,amd64 only).
The later retrieves the E820 as seen by the hypervisor (completely unchanged) and the second call sets the E820 for the specified guest.
tools/libxc/xc_domain.c +52 -25
@@ -478,37 +478,64 @@ int xc_domain_pin_memory_cacheattr(xc_in }#if defined(__i386__) || defined(__x86_64__) -#include "xc_e820.h" +int xc_domain_set_memory_map (xc_interface *xch, +uint32_t domid, +struct e820entry entries[], +uint32_t nr_entries) +{ +int rc; +struct xen_foreign_memory_map fmap = { + .domid = domid, + .map = { .nr_entries = nr_entries } + }; +DECLARE_HYPERCALL_BOUNCE (entries, nr_entries *sizeof (struct e820entry ), +XC_HYPERCALL_BUFFER_BOUNCE_IN ); + +if ( !entries ||xc_hypercall_bounce_pre (xch, entries) ) +return -1 ; + +set_xen_guest_handle (fmap.map.buffer, entries); + + rc =do_memory_op (xch, XENMEM_set_memory_map, &fmap,sizeof (fmap)); + +xc_hypercall_bounce_post (xch, entries); + +return rc; +} +int xc_get_machine_memory_map (xc_interface *xch, +struct e820entry entries[], +uint32_t max_entries) +{ +int rc; +struct xen_memory_map memmap = { + .nr_entries = max_entries + }; +DECLARE_HYPERCALL_BOUNCE (entries,sizeof (struct e820entry ) * max_entries, +XC_HYPERCALL_BUFFER_BOUNCE_OUT ); + +if ( !entries ||xc_hypercall_bounce_pre (xch, entries) || max_entries <=1 ) +return -1 ; + + +set_xen_guest_handle (memmap.buffer, entries); + + rc =do_memory_op (xch, XENMEM_machine_memory_map, &memmap,sizeof (memmap)); + +xc_hypercall_bounce_post (xch, entries); + +return rc ? rc : memmap.nr_entries; +}int xc_domain_set_memmap_limit (xc_interface *xch,uint32_t domid,unsigned long map_limitkb) { -int rc; -struct xen_foreign_memory_map fmap = { - .domid = domid, - .map = { .nr_entries =1 } - }; - DECLARE_HYPERCALL_BUFFER(struct e820entry, e820); +struct e820entry e820; - e820 =xc_hypercall_buffer_alloc (xch, e820,sizeof (*e820)); + e820.addr =0 ; + e820.size = (uint64_t )map_limitkb <<10 ; + e820.type =E820_RAM ; -if ( e820 ==NULL ) - { -PERROR ("Could not allocate memory for xc_domain_set_memmap_limit hypercall" ); -return -1 ; - } - - e820->addr =0 ; - e820->size = (uint64_t )map_limitkb <<10 ; - e820->type =E820_RAM ; - -set_xen_guest_handle (fmap.map.buffer, e820); - - rc =do_memory_op (xch, XENMEM_set_memory_map, &fmap,sizeof (fmap)); - -xc_hypercall_buffer_free (xch, e820); - -return rc; +return xc_domain_set_memory_map (xch, domid, &e820,1 ); }#else int xc_domain_set_memmap_limit(xc_interface *xch,
tools/libxc/xc_e820.h +3 -0
@@ -26,6 +26,9 @@#define E820_RESERVED 2#define E820_ACPI 3#define E820_NVS 4 +#define E820_UNUSABLE 5 + +#define E820MAX (128)struct e820entry {uint64_t addr;
tools/libxc/xenctrl.h +11 -0
@@ -966,6 +966,17 @@ int xc_domain_set_memmap_limit(xc_interfuint32_t domid, unsigned long map_limitkb); +#if defined(__i386__) || defined(__x86_64__) +#include "xc_e820.h" +int xc_domain_set_memory_map (xc_interface *xch, +uint32_t domid, +struct e820entry entries[], +uint32_t nr_entries); + +int xc_get_machine_memory_map (xc_interface *xch, +struct e820entry entries[], +uint32_t max_entries); +#endif int xc_domain_set_time_offset (xc_interface *xch,uint32_t domid,int32_t time_offset_seconds);
PATCH 1/1 x86: make the pv-only e820 array be dynamic
In reply to Konrad Rzeszutek Wilk# HG changeset patch
# Parent 6c05be60fbc74f5d3c751a379ce5c4a147e34132
x86: make the pv-only e820 array be dynamic.
During creation of the PV domain we allocate the E820 structure to have the amount of E820 entries on the machine, plus the number three.
This will allow the tool stack to fill the E820 with more than three entries. Specifically the use cases is , where the toolstack retrieves the E820, sanitizes it, and then sets it for the PV guest (for PCI passthrough), this dynamic number of E820 is just right.
xen/arch/x86/domain.c +4 -0
@@ -657,6 +657,8 @@ int arch_domain_create(struct domain *d,/* 32-bit PV guest by default only if Xen is not 64-bit. */ d->arch.is_32bit_pv = d->arch.has_32bit_shinfo = (CONFIG_PAGING_LEVELS !=4 ); + +spin_lock_init (&d->arch.pv_domain.e820_lock); }/* initialize default tsc behavior in case tools don't */
@@ -696,6 +698,8 @@ void arch_domain_destroy(struct domain *if (is_hvm_domain (d) )hvm_domain_destroy (d); +else +xfree (d->arch.pv_domain.e820);vmce_destroy_msr (d);pci_release_devices (d);
xen/arch/x86/mm.c +36 -8
81 lines not on this page · raw message
xen/include/asm-x86/domain.h +2 -1
@@ -241,7 +241,8 @@ struct pv_domainunsigned long pirq_eoi_map_mfn;/* Pseudophysical e820 map (XENMEM_memory_map). */ -struct e820entry e820[3 ]; +spinlock_t e820_lock; +struct e820entry *e820;unsigned int nr_e820; };
PATCH 1/1 libxl: Add support for passing in the machine's E820 for PCI passthrough triggered by the guest
In reply to Konrad Rzeszutek Wilk# HG changeset patch
# Parent a81f4c7b4e393f0e2cd855e86cf3bfb1a8308ee0
libxl: Add support for passing in the machine's E820 for PCI passthrough
The code that populates E820 is unconditionally triggered by the guest configuration having "pci=['<BDF>,..']", being a PV guest, and if b_info->u.pv.machine_e820 is set.
The code do_domain_create calls the libxl__e820_alloc when it notices that the guest is PV, has at least one PCI devices, and has the machine_e820 flag set.
libxl__e820_alloc calls the xc_get_machine_memory_map to retrieve the systems E820. Then the E820 is sanitized to weed out E820 entries below 16MB, and as well remove any E820_RAM or E820_UNUSED regions as the guest does not need to know about them. The guest only needs the E820_ACPI, E820_NVS, E820_RESERVED to get an idea of where the PCI I/O space is. Mostly.. The Linux kernel assumes that any gap in the E820 is considered PCI I/O space which means that if we pass in the guest 2GB, and the E820_ACPI, and its friend start at 3GB, the gap between 2GB and 3GB will be considered as PCI I/O space. To guard against that we also create an E820_UNUSABLE between the region of 'target_kb' (called ram_end in the code) up to the first E820_[ACPI,NVS,RESERVED] region. Lastly, the xc_domain_set_memory_map is called to install the new E820.
When tested with another PV guest (NetBSD 5.1) the modified E820 gave it no trouble. The code has also been tested with older "classic" Xen Linux and with the newer "pvops" with success (SLES11, RHEL5, Ubuntu Lucid, Debian Squeeze, 2.6.37, 2.6.38, 2.6.39).
Memory that is slack or for balloon (so 'maxmem' in guest configuration) is put behind the machine E820. Which in most cases is after the 4GB.
The reason for doing the fetching of the E820 using the hypercall in the toolstack (instead of the guest doing it) is that when a guest would do a hypercall to 'XENMEM_machine_memory_map' it would retrieve an E820 with I/O range caps added in. Meaning that the region after 4GB up to end of possible memory would be marked as unusable and the kernel would not have any space to allocate a balloon region.
tools/libxl/libxl.idl +1 -0
@@ -118,6 +118,7 @@ libxl_domain_build_info = Struct("domain ("cmdline", string), ("ramdisk", libxl_file_reference), ("features", string, True), + ("machine_e820", bool, False, "Use machine's E820 for PCI passthrough."), ])), ])), ],
tools/libxl/libxl_create.c +8 -0
@@ -516,6 +516,14 @@ static int do_domain_create(libxl__gc *gfor (i =0 ; i < d_config->num_pcidevs; i++)libxl__device_pci_add (gc, domid, &d_config->pcidevs[i],1 ); +if (!d_config->c_info.hvm && d_config->b_info.u.pv.machine_e820) { +int rc =0 ; + rc =libxl__e820_alloc (ctx, domid, d_config); +if (rc) +LIBXL__LOG (ctx,LIBXL__LOG_WARNING , +"Failed while collecting E820 with: %d (errno:%d)\n" , + rc, errno); + }if ( cb && (d_config->c_info.hvm || d_config->b_info.u.pv.bootloader )) {if ( (*cb)(ctx, domid, priv) ) goto error_out;
tools/libxl/libxl_internal.h +1 -0
@@ -344,4 +344,5 @@ _hidden int libxl__error_set(libxl__gc * _hidden int libxl__file_reference_map(libxl_file_reference *f); _hidden int libxl__file_reference_unmap(libxl_file_reference *f); +_hidden int libxl__e820_alloc(libxl_ctx *ctx, uint32_t domid, libxl_domain_config *d_config);#endif
tools/libxl/libxl_pci.c +154 -0
157 lines not on this page · raw message
tools/libxl/xl_cmdimpl.c +3 -0
@@ -373,6 +373,7 @@ static void printf_info(int domid,printf ("\t\t\t(kernel %s)\n" , b_info->kernel.path);printf ("\t\t\t(cmdline %s)\n" , b_info->u.pv.cmdline);printf ("\t\t\t(ramdisk %s)\n" , b_info->u.pv.ramdisk.path); +printf ("\t\t\t(machine_e820 %d)\n" , b_info->u.pv.machine_e820);printf ("\t\t)\n" ); }printf ("\t)\n" );
@@ -984,6 +985,8 @@ skip_vfb:if (!libxl_device_pci_parse_bdf (ctx, pcidev, buf)) d_config->num_pcidevs++; } +if (d_config->num_pcidevs && !c_info->hvm) + b_info->u.pv.machine_e820 = true; }switch (xlu_cfg_get_list (config,"cpuid" , &cpuids,0 ,1 )) {
PATCH 1/1 libxl: Convert E820_UNUSABLE and E820_RAM to E820_UNUSABLE as appropriate.
In reply to Konrad Rzeszutek Wilk# HG changeset patch
# User Konrad Rzeszutek Wilk <[email protected]>
# Date 1302640161 14400
# Node ID cc15803af0318c92ad18b57d9bd7c22b323d5c6b
# Parent 6377bb56ffd1f796a8bf07bf6799cbe111176c39
libxl: Convert E820_UNUSABLE and E820_RAM to E820_UNUSABLE as appropriate.
Most machines after the RAM regions in the e802 have a couple of E820_RESERVED, with E820_ACPI and E820_NVS. On some Intel machines, the E820 looks like swiss cheese:
(XEN) Initial Xen-e820 RAM map:
(XEN) 0000000000000000 - 000000000009d000 (usable) (XEN) 000000000009d000 - 00000000000a0000 (reserved) (XEN) 00000000000e0000 - 0000000000100000 (reserved) (XEN) 0000000000100000 - 000000009cf66000 (usable) (XEN) 000000009cf66000 - 000000009d102000 (ACPI NVS) (XEN) 000000009d102000 - 000000009f6bd000 (usable) <-- (XEN) 000000009f6bd000 - 000000009f6bf000 (reserved) (XEN) 000000009f6bf000 - 000000009f714000 (usable) <-- (XEN) 000000009f714000 - 000000009f7bf000 (ACPI NVS) (XEN) 000000009f7bf000 - 000000009f7e0000 (usable) <-- (XEN) 000000009f7e0000 - 000000009f7ff000 (ACPI data) (XEN) 000000009f7ff000 - 000000009f800000 (usable) <-- (XEN) 000000009f800000 - 00000000a0000000 (reserved) (XEN) 00000000a0000000 - 00000000b0000000 (reserved) (XEN) 00000000fc000000 - 00000000fd000000 (reserved) (XEN) 00000000ffe00000 - 0000000100000000 (reserved) (XEN) 0000000100000000 - 0000000160000000 (usable)
Which means we have to pay attention to the E820_RAM that are between the E820_[ACPI,NVS,RESERVED]. If we remove those E820_RAM (b/c the amount of memory passed to the guest is less that where those E820 regions reside) from the E820, the Linux kernel interprets those "gaps" as PCI I/O space. This is what we are currently doing.
This can be disastrous if we pass in an Intel IGD card which tries to use the first available PCI I/O space - and ends up using the MFNs which are actually RAM instead of being the PCI I/O space.
To make this work, we convert all E820_RAM that are above the 'target_kb' (those that overlap the 'target_kb'
are truncated appropriately) to be E820_UNUSABLE. We also limit this alternation up to 4GB. This means that an E820 for a guest from this (target_kb=1024, maxmem=2048):
[ 0.000000] Set 405658 page(s) to 1-1 mapping. [ 0.000000] BIOS-provided physical RAM map: [ 0.000000] Xen: 0000000000000000 - 00000000000a0000 (usable) [ 0.000000] Xen: 00000000000a0000 - 0000000000100000 (reserved) [ 0.000000] Xen: 0000000000100000 - 0000000040000000 (usable) [ 0.000000] Xen: 0000000040000000 - 000000009cf66000 (unusable) [ 0.000000] Xen: 000000009cf66000 - 000000009d102000 (ACPI NVS) [ 0.000000] Xen: 000000009f6bd000 - 000000009f6bf000 (reserved) [ 0.000000] Xen: 000000009f714000 - 000000009f7bf000 (ACPI NVS) [ 0.000000] Xen: 000000009f7e0000 - 000000009f7ff000 (ACPI data) [ 0.000000] Xen: 000000009f800000 - 00000000b0000000 (reserved) [ 0.000000] Xen: 00000000fc000000 - 00000000fd000000 (reserved) [ 0.000000] Xen: 00000000fec00000 - 00000000fec01000 (reserved) [ 0.000000] Xen: 00000000fee00000 - 00000000fee01000 (reserved) [ 0.000000] Xen: 00000000ffe00000 - 0000000100000000 (reserved) [ 0.000000] Xen: 0000000100000000 - 0000000140800000 (usable)
Will look as so:
[ 0.000000] Set 395880 page(s) to 1-1 mapping. [ 0.000000] BIOS-provided physical RAM map: [ 0.000000] Xen: 0000000000000000 - 00000000000a0000 (usable) [ 0.000000] Xen: 00000000000a0000 - 0000000000100000 (reserved) [ 0.000000] Xen: 0000000000100000 - 0000000040000000 (usable) [ 0.000000] Xen: 0000000040000000 - 000000009cf66000 (unusable) [ 0.000000] Xen: 000000009cf66000 - 000000009d102000 (ACPI NVS) [ 0.000000] Xen: 000000009d102000 - 000000009f6bd000 (unusable) [ 0.000000] Xen: 000000009f6bd000 - 000000009f6bf000 (reserved) [ 0.000000] Xen: 000000009f6bf000 - 000000009f714000 (unusable) [ 0.000000] Xen: 000000009f714000 - 000000009f7bf000 (ACPI NVS) [ 0.000000] Xen: 000000009f7bf000 - 000000009f7e0000 (unusable) [ 0.000000] Xen: 000000009f7e0000 - 000000009f7ff000 (ACPI data) [ 0.000000] Xen: 000000009f7ff000 - 000000009f800000 (unusable) [ 0.000000] Xen: 000000009f800000 - 00000000b0000000 (reserved) [ 0.000000] Xen: 00000000fc000000 - 00000000fd000000 (reserved) [ 0.000000] Xen: 00000000fec00000 - 00000000fec01000 (reserved) [ 0.000000] Xen: 00000000fee00000 - 00000000fee01000 (reserved) [ 0.000000] Xen: 00000000ffe00000 - 0000000100000000 (reserved) [ 0.000000] Xen: 0000000100000000 - 0000000140800000 (usable)
tools/libxl/libxl_pci.c +84 -8
@@ -1114,22 +1114,98 @@ static int e820_sanitize(libxl_ctx *ctx, map_limitkb, ram_end >>12 , delta_kb, start_kb ,start >>12 , balloon_kb); +/* 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 the 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 ; +LIBXL__LOG_ERRNO (ctx,LIBXL__LOG_ERROR ,"Computed E820 wrongly. Continuing on." ); + } + } +/* 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_. */ - e820[idx].type =E820_UNUSABLE ; - e820[idx].addr = ram_end; - e820[idx].size = start - ram_end; - idx++; +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++) { +/* Almost done: copy them over, ignoring the undesireable ones */ +for (i =0 ; i < nr; i++) {if ((src[i].type ==E820_RAM ) || - (src[i].type ==E820_UNUSABLE ) || - (src[i].type ==0 )) + (src[i].type ==0 ))continue ; e820[idx].type = src[i].type; e820[idx].addr = src[i].addr;
Quoted 35 lines · Konrad Rzeszutek Wilk
Hello,
This set of v3 patches allows a PV domain to see the machine's E820 and figure out where the "PCI I/O" gap is and match it with the reality.
Changelog since v2 posting:
- Moved 'libxl__e820_alloc' to be called fromdo_domain_createand ifmachine_e820== true.
- Madeno_machine_e820be set to true, if the guest has no PCI devices (and is PV)
- Used Keir's re-worked code for E820 creation.
Changelog since v1 posting:
- Squashed the "x86: make the pv-only e820 array be dynamic" and "x86: adjust the size of the e820 for pv guest to be dynamic" together.
- Madexc_domain_set_memmap_limituse the 'xc_domain_set_memory_map'
- Moved 'libxl_e820_alloc' and 'libxl_e820_sanitize' to be an internal operation and called from 'libxl_device_pci_parse_bdf'.
- Expanded 'libxl_device_pci_parse_bdf' API call to have an extra argument (optional).The short end is that with these patches a PV domain can:
- Use the correct PCI I/O gap. Before these patches, Linux guest would boot up and would tell:
[ 0.000000] Allocating PCI resources starting at 40000000 (gap: 40000000:c0000000) while in actuality the PCI I/O gap should have been: [ 0.000000] Allocating PCI resources starting at b0000000 (gap: b0000000:4c000000)- The PV domain with PCI devices was limited to 3GB. It now can be booted with 4GB, 8GB, or whatever number you want. The PCI devices will now _not_ conflict with System RAM. Meaning the drivers can load.
- With 2.6.39 kernels (which has the 1-1 mapping code), the
VM_IOflag will be now automatically applied to regions that are considerd PCI I/O regions. You can find out which those are by looking for '1-1' in the kernel bootup.
Quoted 8 lines
To use this patchset, the guest config file has to have the parameter 'pci=['<BDF>',...]' enabled.
This has been tested with 2.6.18 (RHEL5), 2.6.27(SLES11), 2.6.36, 2.6.37, 2.6.38, and 2.6.39 kernels. Also tested with PV NetBSD 5.1.
Tested this with the PCI devices (NIC, MSI), and with 2GB, 4GB, and 6GB guests with success.
Robert, Mikel, Jean,
If you apple these patches and use a fairly modern DomU (git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen.git #master), you should be able to now pass in any PCI device to a guest without any VM_IO type workaround, and with more than 3GB.
It should be pretty obvious when your guest is using this, as the E820 in the dmesg will mirror closely what Dom0 has.