[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH for-4.17] x86/pci: allow BARs to be positioned on e820 reserved regions
The EFI memory map contains two memory types (EfiMemoryMappedIO and EfiMemoryMappedIOPortSpace) used to describe IO memory areas used by EFI firmware. The current parsing of the EFI memory map is translating EfiMemoryMappedIO to E820_RESERVED on x86. This causes issues on some boxes as the firmware is relying on using those regions to position the BARs of devices being used (possibly during runtime) for the firmware. Xen will disable memory decoding on any device that has BARs positioned over any regions on the e820 memory map, hence the firmware will malfunction after Xen turning off memory decoding for the device(s) that have BARs mapped in EfiMemoryMappedIO regions. The system under which this was observed has: EFI memory map: [...] 00000fd000000-00000fe7fffff type=11 attr=800000000000100d [...] 0000:00:1f.5 disabled: BAR [0xfe010, 0xfe010] overlaps with memory map The device behind this BAR is: 00:1f.5 Serial bus controller [0c80]: Intel Corporation Lewisburg SPI Controller (rev 09) Subsystem: Super Micro Computer Inc Device 091c Flags: fast devsel Memory at fe010000 (32-bit, non-prefetchable) [size=4K]well For the record, the symptom observed in that machine was a hard freeze when attempting to set an EFI variable (XEN_EFI_set_variable). Fix by allowing BARs of PCI devices to be positioned over reserved memory regions, but print a warning message about such overlap. Fixes: 75cc460a1b ('xen/pci: detect when BARs are not suitably positioned') Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> --- xen/arch/arm/include/asm/pci.h | 2 -- xen/arch/x86/include/asm/pci.h | 10 ---------- xen/arch/x86/pci.c | 27 +++++++++++++++++++++++++++ xen/include/xen/pci.h | 1 + 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/xen/arch/arm/include/asm/pci.h b/xen/arch/arm/include/asm/pci.h index 8cb46f6b71..80a2431804 100644 --- a/xen/arch/arm/include/asm/pci.h +++ b/xen/arch/arm/include/asm/pci.h @@ -126,8 +126,6 @@ int pci_host_iterate_bridges_and_count(struct domain *d, int pci_host_bridge_mappings(struct domain *d); -bool pci_check_bar(const struct pci_dev *pdev, mfn_t start, mfn_t end); - #else /*!CONFIG_HAS_PCI*/ struct arch_pci_dev { }; diff --git a/xen/arch/x86/include/asm/pci.h b/xen/arch/x86/include/asm/pci.h index f4a58c8acf..c8e1a9ecdb 100644 --- a/xen/arch/x86/include/asm/pci.h +++ b/xen/arch/x86/include/asm/pci.h @@ -57,14 +57,4 @@ static always_inline bool is_pci_passthrough_enabled(void) void arch_pci_init_pdev(struct pci_dev *pdev); -static inline bool pci_check_bar(const struct pci_dev *pdev, - mfn_t start, mfn_t end) -{ - /* - * Check if BAR is not overlapping with any memory region defined - * in the memory map. - */ - return is_memory_hole(start, end); -} - #endif /* __X86_PCI_H__ */ diff --git a/xen/arch/x86/pci.c b/xen/arch/x86/pci.c index 97b792e578..6920bf2168 100644 --- a/xen/arch/x86/pci.c +++ b/xen/arch/x86/pci.c @@ -98,3 +98,30 @@ int pci_conf_write_intercept(unsigned int seg, unsigned int bdf, return rc; } + +bool pci_check_bar(const struct pci_dev *pdev, mfn_t start, mfn_t end) +{ + unsigned long mfn; + + /* + * Check if BAR is not overlapping with any memory region defined + * in the memory map. + */ + if ( is_memory_hole(start, end) ) + return true; + + /* + * Also allow BARs placed on reserved regions in order to deal with EFI + * firmware using EfiMemoryMappedIO regions to place the BARs of devices + * that can be used during runtime. But print a warning when doing so. + */ + for ( mfn = mfn_x(start); mfn <= mfn_x(end); mfn++ ) + if ( !page_is_ram_type(mfn, RAM_TYPE_RESERVED) ) + return false; + + printk(XENLOG_WARNING + "%pp: BAR [%#" PRI_mfn ", %#" PRI_mfn "] overlaps reserved region\n", + &pdev->sbdf, mfn_x(start), mfn_x(end)); + + return true; +} diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h index 5975ca2f30..64995fc68d 100644 --- a/xen/include/xen/pci.h +++ b/xen/include/xen/pci.h @@ -211,6 +211,7 @@ unsigned int pci_size_mem_bar(pci_sbdf_t sbdf, unsigned int pos, void pci_intx(const struct pci_dev *, bool enable); bool_t pcie_aer_get_firmware_first(const struct pci_dev *); +bool pci_check_bar(const struct pci_dev *pdev, mfn_t start, mfn_t end); struct pirq; int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable); -- 2.37.3
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |