j
: Next unread message k
: Previous unread message j a
: Jump to all threads
j l
: Jump to MailingList overview
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@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) {
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@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.