• Michael Ellerman's avatar
    powerpc/io: Fix the IO workarounds code to work with Radix · 43c6494f
    Michael Ellerman authored
    Back in 2006 Ben added some workarounds for a misbehaviour in the
    Spider IO bridge used on early Cell machines, see commit
    014da7ff ("[POWERPC] Cell "Spider" MMIO workarounds"). Later these
    were made to be generic, ie. not tied specifically to Spider.
    
    The code stashes a token in the high bits (59-48) of virtual addresses
    used for IO (eg. returned from ioremap()). This works fine when using
    the Hash MMU, but when we're using the Radix MMU the bits used for the
    token overlap with some of the bits of the virtual address.
    
    This is because the maximum virtual address is larger with Radix, up
    to c00fffffffffffff, and in fact we use that high part of the address
    range for ioremap(), see RADIX_KERN_IO_START.
    
    As it happens the bits that are used overlap with the bits that
    differentiate an IO address vs a linear map address. If the resulting
    address lies outside the linear mapping we will crash (see below), if
    not we just corrupt memory.
    
      virtio-pci 0000:00:00.0: Using 64-bit direct DMA at offset 800000000000000
      Unable to handle kernel paging request for data at address 0xc000000080000014
      ...
      CFAR: c000000000626b98 DAR: c000000080000014 DSISR: 42000000 IRQMASK: 0
      GPR00: c0000000006c54fc c00000003e523378 c0000000016de600 0000000000000000
      GPR04: c00c000080000014 0000000000000007 0fffffff000affff 0000000000000030
             ^^^^
      ...
      NIP [c000000000626c5c] .iowrite8+0xec/0x100
      LR [c0000000006c992c] .vp_reset+0x2c/0x90
      Call Trace:
        .pci_bus_read_config_dword+0xc4/0x120 (unreliable)
        .register_virtio_device+0x13c/0x1c0
        .virtio_pci_probe+0x148/0x1f0
        .local_pci_probe+0x68/0x140
        .pci_device_probe+0x164/0x220
        .really_probe+0x274/0x3b0
        .driver_probe_device+0x80/0x170
        .__driver_attach+0x14c/0x150
        .bus_for_each_dev+0xb8/0x130
        .driver_attach+0x34/0x50
        .bus_add_driver+0x178/0x2f0
        .driver_register+0x90/0x1a0
        .__pci_register_driver+0x6c/0x90
        .virtio_pci_driver_init+0x2c/0x40
        .do_one_initcall+0x64/0x280
        .kernel_init_freeable+0x36c/0x474
        .kernel_init+0x24/0x160
        .ret_from_kernel_thread+0x58/0x7c
    
    This hasn't been a problem because CONFIG_PPC_IO_WORKAROUNDS which
    enables this code is usually not enabled. It is only enabled when it's
    selected by PPC_CELL_NATIVE which is only selected by
    PPC_IBM_CELL_BLADE and that in turn depends on BIG_ENDIAN. So in order
    to hit the bug you need to build a big endian kernel, with IBM Cell
    Blade support enabled, as well as Radix MMU support, and then boot
    that on Power9 using Radix MMU.
    
    Still we can fix the bug, so let's do that. We simply use fewer bits
    for the token, taking the union of the restrictions on the address
    from both Hash and Radix, we end up with 8 bits we can use for the
    token. The only user of the token is iowa_mem_find_bus() which only
    supports 8 token values, so 8 bits is plenty for that.
    
    Fixes: 566ca99a ("powerpc/mm/radix: Add dummy radix_enabled()")
    Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
    43c6494f
io.h 27.9 KB