[PATCH] efifb: avoid reconfiguration of BAR that covers the framebuffer
Ard Biesheuvel
ard.biesheuvel at linaro.org
Tue Mar 21 04:59:16 PDT 2017
On 21 March 2017 at 11:54, Lorenzo Pieralisi <lorenzo.pieralisi at arm.com> wrote:
> [+Bjorn]
>
> On Mon, Mar 20, 2017 at 10:13:57PM +0000, Ard Biesheuvel wrote:
>> On UEFI systems, the PCI subsystem is enumerated by the firmware,
>> and if a graphical framebuffer is exposed by a PCI device, its base
>> address and size are exposed to the OS via the Graphics Output
>> Protocol (GOP).
>>
>> On arm64 PCI systems, the entire PCI hierarchy is reconfigured from
>> scratch at boot. This may result in the GOP framebuffer address to
>> become stale, if the BAR covering the framebuffer is modified. This
>> will cause the framebuffer to become unresponsive, and may in some
>> cases result in unpredictable behavior if the range is reassigned to
>> another device.
>
> How does it currently work on eg x86 ? I suspect it just works because
> on x86 resources are claimed at boot and if the FB memory BAR contains
> reasonable values it is left alone by the kernel code reassigning
> resources on x86.
>
This is my understanding, yes.
>> So add a quirk to the EFI fb driver to find the BAR associated with
>> the GOP base address, and set the IORESOURCE_PCI_FIXED attribute so
>> that the PCI core will leave it alone.
>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
>> ---
>> drivers/video/fbdev/efifb.c | 33 ++++++++++++++++++++
>> 1 file changed, 33 insertions(+)
>>
>> diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
>> index 8c4dc1e1f94f..97a3b15b6f04 100644
>> --- a/drivers/video/fbdev/efifb.c
>> +++ b/drivers/video/fbdev/efifb.c
>> @@ -10,6 +10,7 @@
>> #include <linux/efi.h>
>> #include <linux/errno.h>
>> #include <linux/fb.h>
>> +#include <linux/pci.h>
>> #include <linux/platform_device.h>
>> #include <linux/screen_info.h>
>> #include <video/vga.h>
>> @@ -360,3 +361,35 @@ static struct platform_driver efifb_driver = {
>> };
>>
>> builtin_platform_driver(efifb_driver);
>> +
>> +static bool resource_found;
>> +
>> +static void efifb_fixup_resources(struct pci_dev *dev)
>> +{
>> + u64 fb_base = screen_info.lfb_base;
>> + u64 fb_size = screen_info.lfb_size;
>> + int i;
>> +
>> + if (resource_found || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
>> + return;
>> +
>> + if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
>> + fb_base |= (u64)screen_info.ext_lfb_base << 32;
>> +
>> + if (!fb_base)
>> + return;
>> +
>> + for (i = 0; i < PCI_STD_RESOURCE_END; i++) {
>> + struct resource *res = &dev->resource[i];
>> +
>> + if (!(res->flags & IORESOURCE_MEM))
>> + continue;
>> +
>> + if (res->start <= fb_base && res->end >= fb_base + fb_size) {
>
> You are checking for a live resource here right (ie PCI device should be
> enabled) ? I am not sure that just checking the resource range is safe
> (I mean it would be most certainly a FW bug to have a PCI disabled
> device with memory BAR programmed with the FB addresses but thought it
> was worth mentioning).
>
It is implied that the device is enabled. The GOP protocol exposes a
live framebuffer base/size with some metadata regarding the pixel
format/color depth etc. It contains no annotations as to whether the
device is PCI or simply a framebuffer mapped in system memory, and so
we can only assume that the device is enabled.
>> + res->flags |= IORESOURCE_PCI_FIXED;
>> + resource_found = true;
>> + break;
>> + }
>> + }
>> +}
>> +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, efifb_fixup_resources);
>> --
>> 2.7.4
>>
More information about the linux-arm-kernel
mailing list