|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH] x86/vpci: fix handling of BAR overlaps with non-hole regions
On 15.05.2025 10:41, Roger Pau Monne wrote:
> For once the message printed when a BAR overlaps with a non-hole regions is
> not accurate on x86. While the BAR won't be mapped by the vPCI logic, it
> is quite likely overlapping with a reserved region in the memory map, and
> already mapped as by default all reserved regions are identity mapped in
> the p2m. Fix the message so it just warns about the overlap, without
> mentioning that the BAR won't be mapped, as this has caused confusion in
> the past.
>
> Secondly, when an overlap is detected the BAR 'enabled' field is not set,
> hence other vPCI code that depends on it like vPCI MSI-X handling won't
> function properly, as it sees the BAR as disabled, even when memory
> decoding is enabled for the device and the BAR is likely mapped in the
> p2m. Change the handling of BARs that overlap non-hole regions to instead
> remove any overlapped regions from the rangeset, so the resulting ranges to
> map just contain the hole regions. This requires introducing a new
> pci_sanitize_bar_memory() that's implemented per-arch and sanitizes the
> address range to add to the p2m.
>
> For x86 pci_sanitize_bar_memory() removes any regions present in the host
> memory map, for ARM this is currently left as a dummy handler to not change
> existing behavior.
>
> Ultimately the above changes should fix the vPCI MSI-X handlers not working
> correctly when the BAR that contains the MSI-X table overlaps with a
> non-hole region, as then the 'enabled' BAR bit won't be set and the MSI-X
> traps won't handle accesses as expected.
While all of this reads plausible, I may need to look at this again later,
to hopefully grok the connections and implications.
> --- a/xen/arch/x86/include/asm/pci.h
> +++ b/xen/arch/x86/include/asm/pci.h
> @@ -2,6 +2,7 @@
> #define __X86_PCI_H__
>
> #include <xen/mm.h>
> +#include <xen/rangeset.h>
Please don't, ...
> @@ -57,14 +58,7 @@ 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);
> -}
> +bool pci_check_bar(const struct pci_dev *pdev, mfn_t start, mfn_t end);
> +int pci_sanitize_bar_memory(struct rangeset *r);
... all you need is a struct forward decl here.
> --- a/xen/arch/x86/pci.c
> +++ b/xen/arch/x86/pci.c
> @@ -98,3 +98,53 @@ 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)
> +{
> + /*
> + * Check if BAR is not overlapping with any memory region defined
> + * in the memory map.
> + */
> + if ( !is_memory_hole(start, end) )
> + gdprintk(XENLOG_WARNING,
> + "%pp: BAR at [%"PRI_mfn", %"PRI_mfn"] not in memory map
> hole\n",
> + &pdev->sbdf, mfn_x(start), mfn_x(end));
> +
> + /*
> + * Unconditionally return true, pci_sanitize_bar_memory() will remove any
> + * non-hole regions.
> + */
> + return true;
> +}
> +
> +/* Remove overlaps with any ranges defined in the host memory map. */
> +int pci_sanitize_bar_memory(struct rangeset *r)
> +{
> + unsigned int i;
> +
> + for ( i = 0; i < e820.nr_map; i++ )
> + {
> + const struct e820entry *entry = &e820.map[i];
> + int rc;
> +
> + if ( !entry->size )
> + continue;
> +
> + rc = rangeset_remove_range(r, PFN_DOWN(entry->addr),
> + PFN_UP(entry->addr + entry->size - 1));
> + if ( rc )
> + return rc;
Perhaps better continue the loop in a best effort manner, only accumulating
the error to then ...
> + }
> +
> + return 0;
> +}
... return here?
Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |