Skip to content
  • Mikel Rychliski's avatar
    PCI: Use ioremap(), not phys_to_virt() for platform ROM · 72e0ef0e
    Mikel Rychliski authored
    On some EFI systems, the video BIOS is provided by the EFI firmware.  The
    boot stub code stores the physical address of the ROM image in pdev->rom.
    Currently we attempt to access this pointer using phys_to_virt(), which
    doesn't work with CONFIG_HIGHMEM.
    
    On these systems, attempting to load the radeon module on a x86_32 kernel
    can result in the following:
    
      BUG: unable to handle page fault for address: 3e8ed03c
      #PF: supervisor read access in kernel mode
      #PF: error_code(0x0000) - not-present page
      *pde = 00000000
      Oops: 0000 [#1] PREEMPT SMP
      CPU: 0 PID: 317 Comm: systemd-udevd Not tainted 5.6.0-rc3-next-20200228 #2
      Hardware name: Apple Computer, Inc. MacPro1,1/Mac-F4208DC8, BIOS     MP11.88Z.005C.B08.0707021221 07/02/07
      EIP: radeon_get_bios+0x5ed/0xe50 [radeon]
      Code: 00 00 84 c0 0f 85 12 fd ff ff c7 87 64 01 00 00 00 00 00 00 8b 47 08 8b 55 b0 e8 1e 83 e1 d6 85 c0 74 1a 8b 55 c0 85 d2 74 13 <80> 38 55 75 0e 80 78 01 aa 0f 84 a4 03 00 00 8d 74 26 00 68 dc 06
      EAX: 3e8ed03c EBX: 00000000 ECX: 3e8ed03c EDX: 00010000
      ESI: 00040000 EDI: eec04000 EBP: eef3fc60 ESP: eef3fbe0
      DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 EFLAGS: 00010206
      CR0: 80050033 CR2: 3e8ed03c CR3: 2ec77000 CR4: 000006d0
      Call Trace:
       r520_init+0x26/0x240 [radeon]
       radeon_device_init+0x533/0xa50 [radeon]
       radeon_driver_load_kms+0x80/0x220 [radeon]
       drm_dev_register+0xa7/0x180 [drm]
       radeon_pci_probe+0x10f/0x1a0 [radeon]
       pci_device_probe+0xd4/0x140
    
    Fix the issue by updating all drivers which can access a platform provided
    ROM. Instead of calling the helper function pci_platform_rom() which uses
    phys_to_virt(), call ioremap() directly on the pdev->rom.
    
    radeon_read_platform_bios() previously directly accessed an __iomem
    pointer. Avoid this by calling memcpy_fromio() instead of kmemdup().
    
    pci_platform_rom() now has no remaining callers, so remove it.
    
    Link: https://lore.kernel.org/r/20200319021623.5426-1-mikel@mikelr.com
    
    
    Signed-off-by: default avatarMikel Rychliski <mikel@mikelr.com>
    Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
    Acked-by: default avatarAlex Deucher <alexander.deucher@amd.com>
    72e0ef0e