Message ID | 20170420151743.90889-4-roger.pau@citrix.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Roger, On 20/04/17 16:17, Roger Pau Monne wrote: > And also allow it to do non-identity mappings by adding a new parameter. This > function will be needed in other parts apart from PVH Dom0 build. > > Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> > --- > Cc: Jan Beulich <jbeulich@suse.com> > Cc: Andrew Cooper <andrew.cooper3@citrix.com> > --- > xen/arch/x86/hvm/dom0_build.c | 22 +--------------------- > xen/common/memory.c | 34 ++++++++++++++++++++++++++++++++++ > xen/include/xen/p2m-common.h | 4 ++++ > 3 files changed, 39 insertions(+), 21 deletions(-) > > diff --git a/xen/arch/x86/hvm/dom0_build.c b/xen/arch/x86/hvm/dom0_build.c > index ca88c5835e..65f606d33a 100644 > --- a/xen/arch/x86/hvm/dom0_build.c > +++ b/xen/arch/x86/hvm/dom0_build.c > @@ -64,27 +64,7 @@ static struct acpi_madt_nmi_source __initdata *nmisrc; > static int __init modify_identity_mmio(struct domain *d, unsigned long pfn, > unsigned long nr_pages, const bool map) > { > - int rc; > - > - for ( ; ; ) > - { > - rc = (map ? map_mmio_regions : unmap_mmio_regions) > - (d, _gfn(pfn), nr_pages, _mfn(pfn)); > - if ( rc == 0 ) > - break; > - if ( rc < 0 ) > - { > - printk(XENLOG_WARNING > - "Failed to identity %smap [%#lx,%#lx) for d%d: %d\n", > - map ? "" : "un", pfn, pfn + nr_pages, d->domain_id, rc); > - break; > - } > - nr_pages -= rc; > - pfn += rc; > - process_pending_softirqs(); > - } > - > - return rc; > + return modify_mmio(d, pfn, pfn, nr_pages, map); > } > > /* Populate a HVM memory range using the biggest possible order. */ > diff --git a/xen/common/memory.c b/xen/common/memory.c > index 52879e7438..0d970482cb 100644 > --- a/xen/common/memory.c > +++ b/xen/common/memory.c > @@ -1438,6 +1438,40 @@ int prepare_ring_for_helper( > return 0; > } > > +int modify_mmio(struct domain *d, unsigned long gfn, unsigned long pfn, Whilst you introduce this new function, please use mfn_t and gfn_t. Also s/pfn/mfn/ > + unsigned long nr_pages, const bool map) > +{ > + int rc; > + > + /* > + * Make sure this function is only used by the hardware domain, because it > + * can take an arbitrary long time, and could DoS the whole system. > + */ > + ASSERT(is_hardware_domain(d)); What would be the plan for guest if we decide to use vpci? > + > + for ( ; ; ) > + { > + rc = (map ? map_mmio_regions : unmap_mmio_regions) On ARM, map_mmio_regions and unmap_mmio_regions will map the MMIO with very strict attribute. I think we would need an extra argument to know the wanted memory attribute (maybe p2m_type_t?). > + (d, _gfn(gfn), nr_pages, _mfn(pfn)); > + if ( rc == 0 ) > + break; > + if ( rc < 0 ) > + { > + printk(XENLOG_WARNING I would probably use XENLOG_G_WARNING. > + "Failed to %smap [%#lx, %#lx) -> [%#lx,%#lx) for d%d: %d\n", > + map ? "" : "un", gfn, gfn + nr_pages, pfn, pfn + nr_pages, > + d->domain_id, rc); > + break; > + } > + nr_pages -= rc; > + pfn += rc; > + gfn += rc; > + process_pending_softirqs(); > + } > + > + return rc; > +} > + > /* > * Local variables: > * mode: C > diff --git a/xen/include/xen/p2m-common.h b/xen/include/xen/p2m-common.h > index 8cd5a6b503..1308da44e7 100644 > --- a/xen/include/xen/p2m-common.h > +++ b/xen/include/xen/p2m-common.h > @@ -13,4 +13,8 @@ int unmap_mmio_regions(struct domain *d, > unsigned long nr, > mfn_t mfn); > > + Spurious newline. > +int modify_mmio(struct domain *d, unsigned long gfn, unsigned long pfn, > + unsigned long nr_pages, const bool map); > + > #endif /* _XEN_P2M_COMMON_H */ > Cheers,
On Mon, Apr 24, 2017 at 03:42:08PM +0100, Julien Grall wrote: > On 20/04/17 16:17, Roger Pau Monne wrote: > > /* Populate a HVM memory range using the biggest possible order. */ > > diff --git a/xen/common/memory.c b/xen/common/memory.c > > index 52879e7438..0d970482cb 100644 > > --- a/xen/common/memory.c > > +++ b/xen/common/memory.c > > @@ -1438,6 +1438,40 @@ int prepare_ring_for_helper( > > return 0; > > } > > > > +int modify_mmio(struct domain *d, unsigned long gfn, unsigned long pfn, > > Whilst you introduce this new function, please use mfn_t and gfn_t. > > Also s/pfn/mfn/ Done. > > + unsigned long nr_pages, const bool map) > > +{ > > + int rc; > > + > > + /* > > + * Make sure this function is only used by the hardware domain, because it > > + * can take an arbitrary long time, and could DoS the whole system. > > + */ > > + ASSERT(is_hardware_domain(d)); > > What would be the plan for guest if we decide to use vpci? One option would be to not allow the DomU to relocate it's BARs and ignore writes to the 2nd bit of the command register (PCI_COMMAND_MEMORY), thus always having the BARs mapped. The other is to somehow allow VMExit (and the ARM equivalent) continuation (something similar to what we do with hypercalls). > > + > > + for ( ; ; ) > > + { > > + rc = (map ? map_mmio_regions : unmap_mmio_regions) > > On ARM, map_mmio_regions and unmap_mmio_regions will map the MMIO with very > strict attribute. I think we would need an extra argument to know the wanted > memory attribute (maybe p2m_type_t?). I'm not sure I can do anything regarding this ATM. Sorry for my ignorance, but map_mmio_regions on ARM maps the region as p2m_mmio_direct_dev, and according to the comment that's "Read/write mapping of genuine Device MMIO area", which fits exactly into my usage (I'm using it to map BARs). > > + (d, _gfn(gfn), nr_pages, _mfn(pfn)); > > + if ( rc == 0 ) > > + break; > > + if ( rc < 0 ) > > + { > > + printk(XENLOG_WARNING > > I would probably use XENLOG_G_WARNING. Done. > > + "Failed to %smap [%#lx, %#lx) -> [%#lx,%#lx) for d%d: %d\n", > > + map ? "" : "un", gfn, gfn + nr_pages, pfn, pfn + nr_pages, > > + d->domain_id, rc); > > + break; > > + } > > + nr_pages -= rc; > > + pfn += rc; > > + gfn += rc; > > + process_pending_softirqs(); > > + } > > + > > + return rc; > > +} > > + > > /* > > * Local variables: > > * mode: C > > diff --git a/xen/include/xen/p2m-common.h b/xen/include/xen/p2m-common.h > > index 8cd5a6b503..1308da44e7 100644 > > --- a/xen/include/xen/p2m-common.h > > +++ b/xen/include/xen/p2m-common.h > > @@ -13,4 +13,8 @@ int unmap_mmio_regions(struct domain *d, > > unsigned long nr, > > mfn_t mfn); > > > > + > > Spurious newline. Done. Thanks for the comments.
Hi Roger, On 25/04/2017 09:01, Roger Pau Monne wrote: > On Mon, Apr 24, 2017 at 03:42:08PM +0100, Julien Grall wrote: >> On 20/04/17 16:17, Roger Pau Monne wrote: >>> /* Populate a HVM memory range using the biggest possible order. */ >>> diff --git a/xen/common/memory.c b/xen/common/memory.c >>> index 52879e7438..0d970482cb 100644 >>> --- a/xen/common/memory.c >>> +++ b/xen/common/memory.c >>> @@ -1438,6 +1438,40 @@ int prepare_ring_for_helper( >>> return 0; >>> } >>> >>> +int modify_mmio(struct domain *d, unsigned long gfn, unsigned long pfn, >> >> Whilst you introduce this new function, please use mfn_t and gfn_t. >> >> Also s/pfn/mfn/ > > Done. > >>> + unsigned long nr_pages, const bool map) >>> +{ >>> + int rc; >>> + >>> + /* >>> + * Make sure this function is only used by the hardware domain, because it >>> + * can take an arbitrary long time, and could DoS the whole system. >>> + */ >>> + ASSERT(is_hardware_domain(d)); >> >> What would be the plan for guest if we decide to use vpci? > > One option would be to not allow the DomU to relocate it's BARs and ignore > writes to the 2nd bit of the command register (PCI_COMMAND_MEMORY), thus always > having the BARs mapped. The other is to somehow allow VMExit (and the ARM > equivalent) continuation (something similar to what we do with hypercalls). My understanding is BARs may be allocated by the kernel because the firmware didn't do it. This is the current case on ARM (and I guess x86) where Linux will always go through the BARs. So if you do the first option, who would decide the position of the BARs? For the second option, we can take advantage of superpage (4K, 2M, 1G) mapping on ARM, so the number of actual mapping would be really limited. Also, we are looking at MMIO continuation for ARM for other part of the hypervisor. We might be able to leverage that for this function. > >>> + >>> + for ( ; ; ) >>> + { >>> + rc = (map ? map_mmio_regions : unmap_mmio_regions) >> >> On ARM, map_mmio_regions and unmap_mmio_regions will map the MMIO with very >> strict attribute. I think we would need an extra argument to know the wanted >> memory attribute (maybe p2m_type_t?). > > I'm not sure I can do anything regarding this ATM. Sorry for my ignorance, but > map_mmio_regions on ARM maps the region as p2m_mmio_direct_dev, and according > to the comment that's "Read/write mapping of genuine Device MMIO area", which > fits exactly into my usage (I'm using it to map BARs). We have few p2m_mmio_direct_* p2m_type because the architecture allows us to have fine grain memory attribute. The p2m type p2m_mmio_direct_dev is very restrictive (unaligned access forbid, non-cacheable, non-gatherable). This should be used for MMIO region that have side-effects and will affect performances. We use this one by default as it will restrict the memory attribute used by the guest. However, this will be an issue for at least cacheable BARs. We had similar issue recently on ARM with SRAM device as driver may do unaligned access and cacheable one. For DOM0 we are using p2m_mmio_direct_c and rely on the OS to restrict the memory attribute when necessary. We cannot do that for guest as this may have some security implications. So for the guest we will do on the case by case basis. For instance we you map BAR, you know the kind and can decide of a proper memory attribute. Cheers,
On Tue, Apr 25, 2017 at 10:09:34AM +0100, Julien Grall wrote: > On 25/04/2017 09:01, Roger Pau Monne wrote: > > On Mon, Apr 24, 2017 at 03:42:08PM +0100, Julien Grall wrote: > > > On 20/04/17 16:17, Roger Pau Monne wrote: > > > > + unsigned long nr_pages, const bool map) > > > > +{ > > > > + int rc; > > > > + > > > > + /* > > > > + * Make sure this function is only used by the hardware domain, because it > > > > + * can take an arbitrary long time, and could DoS the whole system. > > > > + */ > > > > + ASSERT(is_hardware_domain(d)); > > > > > > What would be the plan for guest if we decide to use vpci? > > > > One option would be to not allow the DomU to relocate it's BARs and ignore > > writes to the 2nd bit of the command register (PCI_COMMAND_MEMORY), thus always > > having the BARs mapped. The other is to somehow allow VMExit (and the ARM > > equivalent) continuation (something similar to what we do with hypercalls). > > My understanding is BARs may be allocated by the kernel because the firmware > didn't do it. This is the current case on ARM (and I guess x86) where Linux > will always go through the BARs. No, on x86 BARs are allocated by the firmware. Linux or whatever OS will scan the BARs in order to get it's position/size, but will not try to move them AFAIK. > So if you do the first option, who would decide the position of the BARs? On x86 that would be what the firmware has set. > For the second option, we can take advantage of superpage (4K, 2M, 1G) > mapping on ARM, so the number of actual mapping would be really limited. IIRC x86 should also do MMIO mappings with superpages. Maybe we should time how long this takes and then make a decision. > Also, we are looking at MMIO continuation for ARM for other part of the > hypervisor. We might be able to leverage that for this function. Indeed > > > > > > + > > > > + for ( ; ; ) > > > > + { > > > > + rc = (map ? map_mmio_regions : unmap_mmio_regions) > > > > > > On ARM, map_mmio_regions and unmap_mmio_regions will map the MMIO with very > > > strict attribute. I think we would need an extra argument to know the wanted > > > memory attribute (maybe p2m_type_t?). > > > > I'm not sure I can do anything regarding this ATM. Sorry for my ignorance, but > > map_mmio_regions on ARM maps the region as p2m_mmio_direct_dev, and according > > to the comment that's "Read/write mapping of genuine Device MMIO area", which > > fits exactly into my usage (I'm using it to map BARs). > > We have few p2m_mmio_direct_* p2m_type because the architecture allows us to > have fine grain memory attribute. > > The p2m type p2m_mmio_direct_dev is very restrictive (unaligned access > forbid, non-cacheable, non-gatherable). This should be used for MMIO region > that have side-effects and will affect performances. > > We use this one by default as it will restrict the memory attribute used by > the guest. However, this will be an issue for at least cacheable BARs. We > had similar issue recently on ARM with SRAM device as driver may do > unaligned access and cacheable one. > > For DOM0 we are using p2m_mmio_direct_c and rely on the OS to restrict the > memory attribute when necessary. We cannot do that for guest as this may > have some security implications. > > So for the guest we will do on the case by case basis. For instance we you > map BAR, you know the kind and can decide of a proper memory attribute. Oh, OK. I guess you can add a new parameter to pass whether the BAR is prefetchable or not. Roger.
>>> On 25.04.17 at 11:25, <roger.pau@citrix.com> wrote: > On Tue, Apr 25, 2017 at 10:09:34AM +0100, Julien Grall wrote: >> My understanding is BARs may be allocated by the kernel because the firmware >> didn't do it. This is the current case on ARM (and I guess x86) where Linux >> will always go through the BARs. > > No, on x86 BARs are allocated by the firmware. Linux or whatever OS will scan > the BARs in order to get it's position/size, but will not try to move them > AFAIK. That depends. Firmware is not required to set up all of them (only such on devices needed for booting obviously need to be set up). And Linux may (voluntarily or forced via command line option) still move BARs. Jan
On Tue, Apr 25, 2017 at 03:32:50AM -0600, Jan Beulich wrote: > >>> On 25.04.17 at 11:25, <roger.pau@citrix.com> wrote: > > On Tue, Apr 25, 2017 at 10:09:34AM +0100, Julien Grall wrote: > >> My understanding is BARs may be allocated by the kernel because the firmware > >> didn't do it. This is the current case on ARM (and I guess x86) where Linux > >> will always go through the BARs. > > > > No, on x86 BARs are allocated by the firmware. Linux or whatever OS will scan > > the BARs in order to get it's position/size, but will not try to move them > > AFAIK. > > That depends. Firmware is not required to set up all of them (only > such on devices needed for booting obviously need to be set up). > And Linux may (voluntarily or forced via command line option) still > move BARs. Right. In this series I allow the guest to change the position where the BARs are mapped into the guest p2m, but I don't allow it to change the physical address where the BAR is actually mapped. This might work well if all BARs where positioned by the firmware, but if there are unset BARs I don't think Xen is capable to make a good decision about it's position (because it lacks information like ACPI OperationRegions), so I guess I should allow Dom0 to write directly to the BAR and position it. BTW, how does Xen deal with MSI-X tables inside of BARs? AFAICT a PV Dom0 is able to move the BARs around as much as it wants. Roger.
>>> On 26.04.17 at 10:26, <roger.pau@citrix.com> wrote: > BTW, how does Xen deal with MSI-X tables inside of BARs? AFAICT a PV Dom0 is > able to move the BARs around as much as it wants. The current expectation is that this doesn't happen with (pre) set up MSI-X interrupts (i.e. do BAR placement first, then set up interrupts). Jan
On Tue, Apr 25, 2017 at 03:32:50AM -0600, Jan Beulich wrote: > >>> On 25.04.17 at 11:25, <roger.pau@citrix.com> wrote: > > On Tue, Apr 25, 2017 at 10:09:34AM +0100, Julien Grall wrote: > >> My understanding is BARs may be allocated by the kernel because the firmware > >> didn't do it. This is the current case on ARM (and I guess x86) where Linux > >> will always go through the BARs. > > > > No, on x86 BARs are allocated by the firmware. Linux or whatever OS will scan > > the BARs in order to get it's position/size, but will not try to move them > > AFAIK. > > That depends. Firmware is not required to set up all of them (only > such on devices needed for booting obviously need to be set up). > And Linux may (voluntarily or forced via command line option) still > move BARs. The spec seems more strict here: "Power-up software needs to build a consistent address map before booting the machine to an operating system. This means it has to determine how much memory is in the system, and how much address space the I/O controllers in the system require. After determining this information, power-up software can map the I/O controllers into reasonable locations and proceed with system boot." This is from PCI LOCAL BUS SPECIFICATION, REV. 3.0. I read that as "firmware will position all the BARs". Moving the BARs is not a huge problem, this series already allows the guest to move where the BARs are mapped in it's p2m, allowing a guest to set the initial BAR position would also be feasible, but I haven't been able to find any device on my boxes that's not initialized by the firmware, hence it would be hard for me to test that. Roger.
Hi roger, On Thu, 27 Apr 2017, 11:02 Roger Pau Monne, <roger.pau@citrix.com> wrote: > On Tue, Apr 25, 2017 at 03:32:50AM -0600, Jan Beulich wrote: > > >>> On 25.04.17 at 11:25, <roger.pau@citrix.com> wrote: > > > On Tue, Apr 25, 2017 at 10:09:34AM +0100, Julien Grall wrote: > > >> My understanding is BARs may be allocated by the kernel because the > firmware > > >> didn't do it. This is the current case on ARM (and I guess x86) where > Linux > > >> will always go through the BARs. > > > > > > No, on x86 BARs are allocated by the firmware. Linux or whatever OS > will scan > > > the BARs in order to get it's position/size, but will not try to move > them > > > AFAIK. > > > > That depends. Firmware is not required to set up all of them (only > > such on devices needed for booting obviously need to be set up). > > And Linux may (voluntarily or forced via command line option) still > > move BARs. > > The spec seems more strict here: > > "Power-up software needs to build a consistent address map before booting > the > machine to an operating system. This means it has to determine how much > memory > is in the system, and how much address space the I/O controllers in the > system > require. After determining this information, power-up software can map the > I/O > controllers into reasonable locations and proceed with system boot." > It does not seem that strict to me. The spec says "power-up software can map". It is neither must nor should. So it may or may not. As we spoke on the PCI passthrough design document the firmware is only required to initialize device at used for boot. So it does not cover hotplug devices nor devices not used for boot. > This is from PCI LOCAL BUS SPECIFICATION, REV. 3.0. I read that as > "firmware > will position all the BARs". > > Moving the BARs is not a huge problem, this series already allows the > guest to > move where the BARs are mapped in it's p2m, allowing a guest to set the > initial > BAR position would also be feasible, but I haven't been able to find any > device > on my boxes that's not initialized by the firmware, hence it would be hard > for > me to test that. > I will have a look on my ARM box when I am back to test it. Cheers, >
>>> On 27.04.17 at 10:58, <roger.pau@citrix.com> wrote: > On Tue, Apr 25, 2017 at 03:32:50AM -0600, Jan Beulich wrote: >> >>> On 25.04.17 at 11:25, <roger.pau@citrix.com> wrote: >> > On Tue, Apr 25, 2017 at 10:09:34AM +0100, Julien Grall wrote: >> >> My understanding is BARs may be allocated by the kernel because the > firmware >> >> didn't do it. This is the current case on ARM (and I guess x86) where Linux >> >> will always go through the BARs. >> > >> > No, on x86 BARs are allocated by the firmware. Linux or whatever OS will > scan >> > the BARs in order to get it's position/size, but will not try to move them >> > AFAIK. >> >> That depends. Firmware is not required to set up all of them (only >> such on devices needed for booting obviously need to be set up). >> And Linux may (voluntarily or forced via command line option) still >> move BARs. > > The spec seems more strict here: > > "Power-up software needs to build a consistent address map before booting the > machine to an operating system. This means it has to determine how much memory > is in the system, and how much address space the I/O controllers in the system > require. After determining this information, power-up software can map the I/O > controllers into reasonable locations and proceed with system boot." I don't view this as more strict: Note how the last sentence says "can map", not "has to" or "will". There are actually downsides to firmware doing it for all devices: Firmware can't know whether the OS is capable of dealing with 64-bit BARs, yet it is undesirable (and perhaps impossible) to place all of them below 4Gb. > Moving the BARs is not a huge problem, this series already allows the guest to > move where the BARs are mapped in it's p2m, allowing a guest to set the initial > BAR position would also be feasible, but I haven't been able to find any device > on my boxes that's not initialized by the firmware, hence it would be hard for > me to test that. Well, you could zap some instead of mapping them into Dom0's p2m, you'd just need to be careful not to zap any which Dom0 needs for booting (in Linux this may be no more than the graphics card and, if used, a plug-in serial card, as everything else ought to come from the initrd). Jan
diff --git a/xen/arch/x86/hvm/dom0_build.c b/xen/arch/x86/hvm/dom0_build.c index ca88c5835e..65f606d33a 100644 --- a/xen/arch/x86/hvm/dom0_build.c +++ b/xen/arch/x86/hvm/dom0_build.c @@ -64,27 +64,7 @@ static struct acpi_madt_nmi_source __initdata *nmisrc; static int __init modify_identity_mmio(struct domain *d, unsigned long pfn, unsigned long nr_pages, const bool map) { - int rc; - - for ( ; ; ) - { - rc = (map ? map_mmio_regions : unmap_mmio_regions) - (d, _gfn(pfn), nr_pages, _mfn(pfn)); - if ( rc == 0 ) - break; - if ( rc < 0 ) - { - printk(XENLOG_WARNING - "Failed to identity %smap [%#lx,%#lx) for d%d: %d\n", - map ? "" : "un", pfn, pfn + nr_pages, d->domain_id, rc); - break; - } - nr_pages -= rc; - pfn += rc; - process_pending_softirqs(); - } - - return rc; + return modify_mmio(d, pfn, pfn, nr_pages, map); } /* Populate a HVM memory range using the biggest possible order. */ diff --git a/xen/common/memory.c b/xen/common/memory.c index 52879e7438..0d970482cb 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -1438,6 +1438,40 @@ int prepare_ring_for_helper( return 0; } +int modify_mmio(struct domain *d, unsigned long gfn, unsigned long pfn, + unsigned long nr_pages, const bool map) +{ + int rc; + + /* + * Make sure this function is only used by the hardware domain, because it + * can take an arbitrary long time, and could DoS the whole system. + */ + ASSERT(is_hardware_domain(d)); + + for ( ; ; ) + { + rc = (map ? map_mmio_regions : unmap_mmio_regions) + (d, _gfn(gfn), nr_pages, _mfn(pfn)); + if ( rc == 0 ) + break; + if ( rc < 0 ) + { + printk(XENLOG_WARNING + "Failed to %smap [%#lx, %#lx) -> [%#lx,%#lx) for d%d: %d\n", + map ? "" : "un", gfn, gfn + nr_pages, pfn, pfn + nr_pages, + d->domain_id, rc); + break; + } + nr_pages -= rc; + pfn += rc; + gfn += rc; + process_pending_softirqs(); + } + + return rc; +} + /* * Local variables: * mode: C diff --git a/xen/include/xen/p2m-common.h b/xen/include/xen/p2m-common.h index 8cd5a6b503..1308da44e7 100644 --- a/xen/include/xen/p2m-common.h +++ b/xen/include/xen/p2m-common.h @@ -13,4 +13,8 @@ int unmap_mmio_regions(struct domain *d, unsigned long nr, mfn_t mfn); + +int modify_mmio(struct domain *d, unsigned long gfn, unsigned long pfn, + unsigned long nr_pages, const bool map); + #endif /* _XEN_P2M_COMMON_H */
And also allow it to do non-identity mappings by adding a new parameter. This function will be needed in other parts apart from PVH Dom0 build. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> --- Cc: Jan Beulich <jbeulich@suse.com> Cc: Andrew Cooper <andrew.cooper3@citrix.com> --- xen/arch/x86/hvm/dom0_build.c | 22 +--------------------- xen/common/memory.c | 34 ++++++++++++++++++++++++++++++++++ xen/include/xen/p2m-common.h | 4 ++++ 3 files changed, 39 insertions(+), 21 deletions(-)