From: Tiejun Chen <tiejun.chen@intel.com>
To: xen-devel@lists.xen.org
Cc: Keir Fraser <keir@xen.org>,
Ian Campbell <ian.campbell@citrix.com>,
Stefano Stabellini <stefano.stabellini@eu.citrix.com>,
Andrew Cooper <andrew.cooper3@citrix.com>,
Ian Jackson <ian.jackson@eu.citrix.com>,
Jan Beulich <jbeulich@suse.com>, Wei Liu <wei.liu2@citrix.com>
Subject: [v11][PATCH 06/16] hvmloader/pci: Try to avoid placing BARs in RMRRs
Date: Wed, 22 Jul 2015 09:29:57 +0800 [thread overview]
Message-ID: <1437528607-19315-7-git-send-email-tiejun.chen@intel.com> (raw)
In-Reply-To: <1437528607-19315-1-git-send-email-tiejun.chen@intel.com>
Try to avoid placing PCI BARs over RMRRs:
- If mmio_hole_size is not specified, and the existing MMIO range has
RMRRs in it, and there is space to expand the hole in lowmem without
moving more memory, then make the MMIO hole as large as possible.
- When placing RMRRs, find the next RMRR higher than the current base
in the lowmem mmio hole. If it overlaps, skip ahead of it and find
the next one.
This certainly won't work in all cases, but it should work in a
significant number of cases. Additionally, users should be able to
work around problems by setting mmio_hole_size larger in the guest
config.
CC: Keir Fraser <keir@xen.org>
CC: Jan Beulich <jbeulich@suse.com>
CC: Andrew Cooper <andrew.cooper3@citrix.com>
CC: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
CC: Ian Campbell <ian.campbell@citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>
Signed-off-by: Tiejun Chen <tiejun.chen@intel.com>
---
v11:
* To find the lowest RMRR the _end_ of which is higher than base.
* Refine some code implementations
v10:
* This is from George' draft patch which implements an acceptable solution in
current cycle. Here I just implemented check_overlap_all() and some cleanups.
v9:
* A little improvement to code implementation but again, its still argued about
this solution.
v8:
* Based on current discussion its hard to reshape the original mmio
allocation mechanism but we haven't a good and simple way to in short term.
So instead, we don't bring more complicated to intervene that process but
still check any conflicts to disable all associated devices.
v6 ~ v7:
* Nothing is changed.
v5:
* Rename that field, is_64bar, inside struct bars with flag, and
then extend to also indicate if this bar is already allocated.
v4:
* We have to re-design this as follows:
#1. Goal
MMIO region should exclude all reserved device memory
#2. Requirements
#2.1 Still need to make sure MMIO region is fit all pci devices as before
#2.2 Accommodate the not aligned reserved memory regions
If I'm missing something let me know.
#3. How to
#3.1 Address #2.1
We need to either of populating more RAM, or of expanding more highmem. But
we should know just 64bit-bar can work with highmem, and as you mentioned we
also should avoid expanding highmem as possible. So my implementation is to
allocate 32bit-bar and 64bit-bar orderly.
1>. The first allocation round just to 32bit-bar
If we can finish allocating all 32bit-bar, we just go to allocate 64bit-bar
with all remaining resources including low pci memory.
If not, we need to calculate how much RAM should be populated to allocate the
remaining 32bit-bars, then populate sufficient RAM as exp_mem_resource to go
to the second allocation round 2>.
2>. The second allocation round to the remaining 32bit-bar
We should can finish allocating all 32bit-bar in theory, then go to the third
allocation round 3>.
3>. The third allocation round to 64bit-bar
We'll try to first allocate from the remaining low memory resource. If that
isn't enough, we try to expand highmem to allocate for 64bit-bar. This process
should be same as the original.
#3.2 Address #2.2
I'm trying to accommodate the not aligned reserved memory regions:
We should skip all reserved device memory, but we also need to check if other
smaller bars can be allocated if a mmio hole exists between resource->base and
reserved device memory. If a hole exists between base and reserved device
memory, lets go out simply to try allocate for next bar since all bars are in
descending order of size. If not, we need to move resource->base to reserved_end
just to reallocate this bar.
tools/firmware/hvmloader/pci.c | 65 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 65 insertions(+)
diff --git a/tools/firmware/hvmloader/pci.c b/tools/firmware/hvmloader/pci.c
index 5ff87a7..74fc080 100644
--- a/tools/firmware/hvmloader/pci.c
+++ b/tools/firmware/hvmloader/pci.c
@@ -38,6 +38,46 @@ uint64_t pci_hi_mem_start = 0, pci_hi_mem_end = 0;
enum virtual_vga virtual_vga = VGA_none;
unsigned long igd_opregion_pgbase = 0;
+/* Check if the specified range conflicts with any reserved device memory. */
+static bool check_overlap_all(uint64_t start, uint64_t size)
+{
+ unsigned int i;
+
+ for ( i = 0; i < memory_map.nr_map; i++ )
+ {
+ if ( memory_map.map[i].type == E820_RESERVED &&
+ check_overlap(start, size,
+ memory_map.map[i].addr,
+ memory_map.map[i].size) )
+ return true;
+ }
+
+ return false;
+}
+
+/* Find the lowest RMRR higher than base. */
+static int find_next_rmrr(uint32_t base)
+{
+ unsigned int i;
+ int next_rmrr = -1;
+ uint64_t end, min_end = (1ull << 32);
+
+ for ( i = 0; i < memory_map.nr_map ; i++ )
+ {
+ end = memory_map.map[i].addr + memory_map.map[i].size;
+
+ if ( memory_map.map[i].type == E820_RESERVED &&
+ end > base &&
+ min_end < min_end )
+ {
+ next_rmrr = i;
+ min_end = end;
+ }
+ }
+
+ return next_rmrr;
+}
+
void pci_setup(void)
{
uint8_t is_64bar, using_64bar, bar64_relocate = 0;
@@ -46,6 +86,7 @@ void pci_setup(void)
uint32_t vga_devfn = 256;
uint16_t class, vendor_id, device_id;
unsigned int bar, pin, link, isa_irq;
+ int next_rmrr;
/* Resources assignable to PCI devices via BARs. */
struct resource {
@@ -299,6 +340,15 @@ void pci_setup(void)
|| (((pci_mem_start << 1) >> PAGE_SHIFT)
>= hvm_info->low_mem_pgend)) )
pci_mem_start <<= 1;
+
+ /*
+ * Try to accomodate RMRRs in our MMIO region on a best-effort basis.
+ * If we have RMRRs in the range, then make pci_mem_start just after
+ * hvm_info->low_mem_pgend.
+ */
+ if ( pci_mem_start > (hvm_info->low_mem_pgend << PAGE_SHIFT) &&
+ check_overlap_all(pci_mem_start, pci_mem_end-pci_mem_start) )
+ pci_mem_start = hvm_info->low_mem_pgend << PAGE_SHIFT;
}
if ( mmio_total > (pci_mem_end - pci_mem_start) )
@@ -352,6 +402,8 @@ void pci_setup(void)
io_resource.base = 0xc000;
io_resource.max = 0x10000;
+ next_rmrr = find_next_rmrr(pci_mem_start);
+
/* Assign iomem and ioport resources in descending order of size. */
for ( i = 0; i < nr_bars; i++ )
{
@@ -407,6 +459,19 @@ void pci_setup(void)
}
base = (resource->base + bar_sz - 1) & ~(uint64_t)(bar_sz - 1);
+
+ /* If we're using mem_resource, check for RMRR conflicts. */
+ while ( resource == &mem_resource &&
+ next_rmrr >= 0 &&
+ check_overlap(base, bar_sz,
+ memory_map.map[next_rmrr].addr,
+ memory_map.map[next_rmrr].size) )
+ {
+ base = memory_map.map[next_rmrr].addr + memory_map.map[next_rmrr].size;
+ base = (base + bar_sz - 1) & ~(bar_sz - 1);
+ next_rmrr = find_next_rmrr(base);
+ }
+
bar_data |= (uint32_t)base;
bar_data_upper = (uint32_t)(base >> 32);
base += bar_sz;
--
1.9.1
next prev parent reply other threads:[~2015-07-22 1:29 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-22 1:29 [v11][PATCH 00/16] Fix RMRR Tiejun Chen
2015-07-22 1:29 ` [v11][PATCH 01/16] xen: introduce XENMEM_reserved_device_memory_map Tiejun Chen
2015-07-22 9:32 ` Jan Beulich
2015-07-22 10:42 ` [PATCH v12] " Jan Beulich
2015-07-22 12:17 ` Julien Grall
2015-07-22 12:28 ` Jan Beulich
2015-07-22 12:52 ` Ian Campbell
2015-07-22 13:14 ` Jan Beulich
2015-07-22 13:19 ` Ian Campbell
2015-07-22 12:55 ` Chen, Tiejun
2015-07-22 13:03 ` Jan Beulich
2015-07-22 13:20 ` Chen, Tiejun
2015-07-22 13:28 ` Jan Beulich
2015-07-22 13:46 ` Ian Campbell
2015-07-22 14:22 ` [PATCH v12a] " Jan Beulich
2015-07-22 1:29 ` [v11][PATCH 02/16] xen/vtd: create RMRR mapping Tiejun Chen
2015-07-22 1:29 ` [v11][PATCH 03/16] xen/passthrough: extend hypercall to support rdm reservation policy Tiejun Chen
2015-07-22 1:29 ` [v11][PATCH 04/16] xen: enable XENMEM_memory_map in hvm Tiejun Chen
2015-07-22 1:29 ` [v11][PATCH 05/16] hvmloader: get guest memory map into memory_map[] Tiejun Chen
2015-07-22 1:29 ` Tiejun Chen [this message]
2015-07-22 8:43 ` [v11][PATCH 06/16] hvmloader/pci: Try to avoid placing BARs in RMRRs Jan Beulich
2015-07-22 13:00 ` Jan Beulich
2015-07-22 1:29 ` [v11][PATCH 07/16] hvmloader/e820: construct guest e820 table Tiejun Chen
2015-07-22 1:29 ` [v11][PATCH 08/16] tools/libxc: Expose new hypercall xc_reserved_device_memory_map Tiejun Chen
2015-07-22 1:30 ` [v11][PATCH 09/16] tools: extend xc_assign_device() to support rdm reservation policy Tiejun Chen
2015-07-22 13:06 ` Ian Jackson
2015-07-22 15:01 ` Wei Liu
2015-07-22 1:30 ` [v11][PATCH 10/16] tools: introduce some new parameters to set rdm policy Tiejun Chen
2015-07-22 1:30 ` [v11][PATCH 11/16] tools/libxl: detect and avoid conflicts with RDM Tiejun Chen
2015-07-22 8:28 ` Jan Beulich
2015-07-22 8:52 ` Chen, Tiejun
2015-07-22 10:12 ` Jan Beulich
2015-07-22 10:54 ` George Dunlap
2015-07-22 10:04 ` Ian Jackson
2015-07-22 16:05 ` Jan Beulich
2015-07-22 13:24 ` Ian Jackson
2015-07-22 13:33 ` Chen, Tiejun
2015-07-22 14:04 ` Ian Jackson
2015-07-22 15:00 ` Chen, Tiejun
2015-07-22 15:09 ` Chen, Tiejun
2015-07-22 15:09 ` Ian Jackson
2015-07-22 15:21 ` Chen, Tiejun
2015-07-22 1:30 ` [v11][PATCH 12/16] tools: introduce a new parameter to set a predefined rdm boundary Tiejun Chen
2015-07-22 1:30 ` [v11][PATCH 13/16] libxl: construct e820 map with RDM information for HVM guest Tiejun Chen
2015-07-22 1:30 ` [v11][PATCH 14/16] xen/vtd: enable USB device assignment Tiejun Chen
2015-07-22 1:30 ` [v11][PATCH 15/16] xen/vtd: prevent from assign the device with shared rmrr Tiejun Chen
2015-07-22 1:30 ` [v11][PATCH 16/16] tools: parse to enable new rdm policy parameters Tiejun Chen
2015-07-22 14:09 ` Ian Jackson
2015-07-22 14:40 ` Wei Liu
2015-07-22 12:38 ` [v11][PATCH 00/16] Fix RMRR Wei Liu
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=1437528607-19315-7-git-send-email-tiejun.chen@intel.com \
--to=tiejun.chen@intel.com \
--cc=andrew.cooper3@citrix.com \
--cc=ian.campbell@citrix.com \
--cc=ian.jackson@eu.citrix.com \
--cc=jbeulich@suse.com \
--cc=keir@xen.org \
--cc=stefano.stabellini@eu.citrix.com \
--cc=wei.liu2@citrix.com \
--cc=xen-devel@lists.xen.org \
/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.