mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen/pci: replace call to is_memory_hole to pci_check_bar
is_memory_hole was implemented for x86 and not for ARM when introduced. Replace is_memory_hole call to pci_check_bar as function should check if device BAR is in defined memory range. Also, add an implementation for ARM which is required for PCI passthrough. On x86, pci_check_bar will call is_memory_hole which will check if BAR is not overlapping with any memory region defined in the memory map. On ARM, pci_check_bar will go through the host bridge ranges and check if the BAR is in the range of defined ranges. Signed-off-by: Rahul Singh <rahul.singh@arm.com> Acked-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
This commit is contained in:
1 parent
943941fb7a
commit
cc80e2bab0
4 files changed
+70
-4
No files matched your search
@@ -126,6 +126,8 @@ 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 { };
|
||||
|
||||
@@ -24,6 +24,16 @@
|
||||
|
||||
#include <asm/setup.h>
|
||||
|
||||
/*
|
||||
* struct to hold pci device bar.
|
||||
*/
|
||||
struct pdev_bar_check
|
||||
{
|
||||
paddr_t start;
|
||||
paddr_t end;
|
||||
bool is_valid;
|
||||
};
|
||||
|
||||
/*
|
||||
* List for all the pci host bridges.
|
||||
*/
|
||||
@@ -363,6 +373,50 @@ int __init pci_host_bridge_mappings(struct domain *d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: BAR addresses and Root Complex window addresses are not guaranteed
|
||||
* to be page aligned. We should check for alignment but this is not the
|
||||
* right place for alignment check.
|
||||
*/
|
||||
static int is_bar_valid(const struct dt_device_node *dev,
|
||||
paddr_t addr, paddr_t len, void *data)
|
||||
{
|
||||
struct pdev_bar_check *bar_data = data;
|
||||
paddr_t s = bar_data->start;
|
||||
paddr_t e = bar_data->end;
|
||||
|
||||
if ( (s >= addr) && (e <= (addr + len - 1)) )
|
||||
bar_data->is_valid = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: Revisit this function when ACPI PCI passthrough support is added. */
|
||||
bool pci_check_bar(const struct pci_dev *pdev, mfn_t start, mfn_t end)
|
||||
{
|
||||
int ret;
|
||||
const struct dt_device_node *dt_node;
|
||||
paddr_t s = mfn_to_maddr(start);
|
||||
paddr_t e = mfn_to_maddr(end);
|
||||
struct pdev_bar_check bar_data = {
|
||||
.start = s,
|
||||
.end = e,
|
||||
.is_valid = false
|
||||
};
|
||||
|
||||
if ( s >= e )
|
||||
return false;
|
||||
|
||||
dt_node = pci_find_host_bridge_node(pdev);
|
||||
if ( !dt_node )
|
||||
return false;
|
||||
|
||||
ret = dt_for_each_range(dt_node, &is_bar_valid, &bar_data);
|
||||
if ( ret < 0 )
|
||||
return false;
|
||||
|
||||
return bar_data.is_valid;
|
||||
}
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
@@ -57,4 +57,14 @@ 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__ */
|
||||
@@ -304,8 +304,8 @@ static void check_pdev(const struct pci_dev *pdev)
|
||||
if ( rc < 0 )
|
||||
/* Unable to size, better leave memory decoding disabled. */
|
||||
return;
|
||||
if ( size && !is_memory_hole(maddr_to_mfn(addr),
|
||||
maddr_to_mfn(addr + size - 1)) )
|
||||
if ( size && !pci_check_bar(pdev, maddr_to_mfn(addr),
|
||||
maddr_to_mfn(addr + size - 1)) )
|
||||
{
|
||||
/*
|
||||
* Return without enabling memory decoding if BAR position is not
|
||||
@@ -331,8 +331,8 @@ static void check_pdev(const struct pci_dev *pdev)
|
||||
|
||||
if ( rc < 0 )
|
||||
return;
|
||||
if ( size && !is_memory_hole(maddr_to_mfn(addr),
|
||||
maddr_to_mfn(addr + size - 1)) )
|
||||
if ( size && !pci_check_bar(pdev, maddr_to_mfn(addr),
|
||||
maddr_to_mfn(addr + size - 1)) )
|
||||
{
|
||||
printk(warn, &pdev->sbdf, "ROM ", PFN_DOWN(addr),
|
||||
PFN_DOWN(addr + size - 1));
|
||||
|
||||