[OpenBIOS] [PATCH] pci: fix setup of 64-bit BARs
Mark Cave-Ayland
mark.cave-ayland at ilande.co.uk
Tue Mar 14 22:35:15 CET 2017
On 11/03/17 14:38, Mark Cave-Ayland wrote:
> The current PCI implementation is designed for a 32-bit PCI bus. When
> a 64-bit BAR is encountered during PCI bus enumeration, currently we
> treat the MSB BAR the same as a standard 32-bit BAR, attempting to guess
> its size by setting to 0xffffffff and reading back the response which
> returns back an invalid size of 0 and fails.
>
> This has the effect of setting the MSB BAR to 0xffffffff meaning that
> 64-bit BARs are mapped at the top of PCI memory in the wrong location.
>
> Handle this case by ignoring the MSB BAR when we detect a 64-bit BAR
> leaving it at its default value of zero. This solves the issue by
> ensuring that all 64-bit BARs are mapped within 32-bit PCI space which
> is fine for the PPC/SPARC64 machines we care about.
>
> Most noticeably this solves the issue of virtio modern devices (which
> use 64-bit BARs under QEMU) causing a kernel panic upon startup on
> qemu-system-sparc64 because they are mapped at the wrong address by OpenBIOS.
>
> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>
> ---
> drivers/pci.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pci.c b/drivers/pci.c
> index c998280..2e09d0a 100644
> --- a/drivers/pci.c
> +++ b/drivers/pci.c
> @@ -1202,9 +1202,9 @@ ob_pci_configure(pci_addr addr, pci_config_t *config, int num_regs, int rom_bar,
> unsigned long *mem_base, unsigned long *io_base)
>
> {
> - uint32_t omask;
> + uint32_t omask, mask;
> uint16_t cmd;
> - int reg;
> + int reg, flags, space_code;
> pci_addr config_addr;
>
> ob_pci_configure_irq(addr, config);
> @@ -1216,6 +1216,14 @@ ob_pci_configure(pci_addr addr, pci_config_t *config, int num_regs, int rom_bar,
> ob_pci_configure_bar(addr, config, reg, config_addr,
> &omask, mem_base,
> io_base);
> +
> + /* Ignore 64-bit BAR MSBs (always map in 32-bit space) */
> + pci_decode_pci_addr(config->assigned[reg],
> + &flags, &space_code, &mask);
> +
> + if (space_code == MEMORY_SPACE_64) {
> + reg++;
> + }
> }
>
> if (rom_bar) {
>
No further comments, so pushed to git master.
ATB,
Mark.
More information about the OpenBIOS
mailing list