efi/earlycon: Remap entire framebuffer after page initialization
PATCH v2 1/1 efi/earlycon: Remap entire framebuffer after page initialization
When the commit 69c1f396f25b ("efi/x86: Convert x86 EFI earlyprintk into generic earlycon implementation") moved x86 specific EFI earlyprintk implementation to shared location it also tweaked the behaviour. In particular it dropped a trick with full framebuffer remapping after page initialization. This led to two regressions:
1) very slow scrolling after page initialization;
2) kernel hang when keep_bootcon parameter is being provided.
Returning the trick back fixes #2 and mitigates, i.e. reduces the window when slowness appears, #1 presumably due to eliminating heavy map()/unmap() operations per each pixel line on the screen.
---
v2:
- add __exitcall()
- swap type and attribute for __init / __exit functions as most used in the kernel
drivers/firmware/efi/earlycon.c | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
drivers/firmware/efi/earlycon.c +34 -0
@@ -17,14 +17,48 @@ static const struct font_desc *font;static u32 efi_x, efi_y;static u64 fb_base;static pgprot_t fb_prot; +static void *efi_fb; + +/* +* efi earlycon needs to use early_memremap() to map the framebuffer. +* But early_memremap() is not usable for 'earlycon=efifb keep_bootcon', +* memremap() should be used instead. memremap() will be available after +* paging_init() which is earlier than initcall callbacks. Thus adding this +* early initcall function early_efi_map_fb() to map the whole efi framebuffer. +*/ +static int __init early_efi_map_fb (void ) +{ +u32 size; + + size = screen_info.lfb_size; +if (pgprot_val (fb_prot) ==pgprot_val (PAGE_KERNEL )) + efi_fb =memremap (fb_base, size,MEMREMAP_WB ); +else + efi_fb =memremap (fb_base, size,MEMREMAP_WC ); + +return efi_fb ?0 : -ENOMEM ; +} +early_initcall (early_efi_map_fb); + +static void __exit early_efi_unmap_fb(void) +{ +memunmap (efi_fb); +} +__exitcall (early_efi_unmap_fb);static __ref void *efi_earlycon_map (unsigned long start,unsigned long len) { +if (efi_fb) +return efi_fb + start; +return early_memremap_prot (fb_base + start, len,pgprot_val (fb_prot)); }static __ref void efi_earlycon_unmap (void *addr,unsigned long len) { +if (efi_fb) +return ; +early_memunmap (addr, len); }
Signature · 1 line
2.24.0
Quoted 11 lines · Andy Shevchenko
When the commit
69c1f396f25b("efi/x86: Convert x86 EFI earlyprintk into generic earlycon implementation") moved x86 specific EFI earlyprintk implementation to shared location it also tweaked the behaviour. In particular it dropped a trick with full framebuffer remapping after page initialization. This led to two regressions:
1) very slow scrolling after page initialization;
2) kernel hang whenkeep_bootconparameter is being provided.Returning the trick back fixes #2 and mitigates, i.e. reduces the window when slowness appears, #1 presumably due to eliminating heavy map()/unmap() operations per each pixel line on the screen.
Please, hold on. I found an issue when no earlycon is not being provided in command line. I will fix, test and send a v3 soon.
Quoted 69 lines
Fixes 69c1f396f25b ("efi/x86: Convert x86 EFI earlyprintk into generic earlycon implementation")Cc Ard Biesheuvel <[email protected]>Cc Alexander Graf <[email protected]>Cc Matt Fleming <[email protected]>Signed-off-by Andy Shevchenko <[email protected]>---
v2:
- add__exitcall()
- swap type and attribute for__init/__exitfunctions as most used in the kerneldrivers/firmware/efi/earlycon.c | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)drivers/firmware/efi/earlycon.c +34
-0@@ -17,14 +17,48 @@ static const struct font_desc *font;static u32 efi_x, efi_y;static u64 fb_base;static pgprot_t fb_prot; +static void *efi_fb; + +/* +* efi earlycon needs to use early_memremap() to map the framebuffer. +* But early_memremap() is not usable for 'earlycon=efifb keep_bootcon', +* memremap() should be used instead. memremap() will be available after +* paging_init() which is earlier than initcall callbacks. Thus adding this +* early initcall function early_efi_map_fb() to map the whole efi framebuffer. +*/ +static int __init early_efi_map_fb (void ) +{ +u32 size; + + size = screen_info.lfb_size; +if (pgprot_val (fb_prot) ==pgprot_val (PAGE_KERNEL )) + efi_fb =memremap (fb_base, size,MEMREMAP_WB ); +else + efi_fb =memremap (fb_base, size,MEMREMAP_WC ); + +return efi_fb ?0 : -ENOMEM ; +} +early_initcall (early_efi_map_fb); + +static void __exit early_efi_unmap_fb(void) +{ +memunmap (efi_fb); +} +__exitcall (early_efi_unmap_fb);static __ref void *efi_earlycon_map (unsigned long start,unsigned long len) { +if (efi_fb) +return efi_fb + start; +return early_memremap_prot (fb_base + start, len,pgprot_val (fb_prot)); }static __ref void efi_earlycon_unmap (void *addr,unsigned long len) { +if (efi_fb) +return ; +early_memunmap (addr, len); }Signature · 1 line
2.24.0
Signature · 2 lines
With Best Regards, Andy Shevchenko
Quoted 10 lines · Andy Shevchenko
Quoted 8 lines · Andy Shevchenko
When the commit
69c1f396f25b("efi/x86: Convert x86 EFI earlyprintk into generic earlycon implementation") moved x86 specific EFI earlyprintk implementation to shared location it also tweaked the behaviour. In particular it dropped a trick with full framebuffer remapping after page initialization. This led to two regressions:
1) very slow scrolling after page initialization;
2) kernel hang whenkeep_bootconparameter is being provided.
Quoted 7 lines
Quoted 3 lines
Returning the trick back fixes #2 and mitigates, i.e. reduces the window when slowness appears, #1 presumably due to eliminating heavy map()/unmap() operations per each pixel line on the screen.
Please, hold on. I found an issue when no earlycon is not being provided in command line. I will fix, test and send a v3 soon.
Ok
Quoted 75 lines
Quoted 67 lines
Fixes 69c1f396f25b ("efi/x86: Convert x86 EFI earlyprintk into generic earlycon implementation")Cc Ard Biesheuvel <[email protected]>Cc Alexander Graf <[email protected]>Cc Matt Fleming <[email protected]>Signed-off-by Andy Shevchenko <[email protected]>---
v2:
- add__exitcall()
- swap type and attribute for__init/__exitfunctions as most used in the kerneldrivers/firmware/efi/earlycon.c | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)drivers/firmware/efi/earlycon.c +34
-1@@ -17,14 +17,48 @@ static const struct font_desc *font;static u32 efi_x, efi_y;static u64 fb_base;static pgprot_t fb_prot; +static void *efi_fb; + +/* +* efi earlycon needs to use early_memremap() to map the framebuffer. +* But early_memremap() is not usable for 'earlycon=efifb keep_bootcon', +* memremap() should be used instead. memremap() will be available after +* paging_init() which is earlier than initcall callbacks. Thus adding this +* early initcall function early_efi_map_fb() to map the whole efi framebuffer. +*/ +static int __init early_efi_map_fb (void ) +{ +u32 size; + + size = screen_info.lfb_size; +if (pgprot_val (fb_prot) ==pgprot_val (PAGE_KERNEL )) + efi_fb =memremap (fb_base, size,MEMREMAP_WB ); +else + efi_fb =memremap (fb_base, size,MEMREMAP_WC ); + +return efi_fb ?0 : -ENOMEM ; +} +early_initcall (early_efi_map_fb); + +static void __exit early_efi_unmap_fb(void) +{ +memunmap (efi_fb); +} +__exitcall (early_efi_unmap_fb);static __ref void *efi_earlycon_map (unsigned long start,unsigned long len) { +if (efi_fb) +return efi_fb + start; +return early_memremap_prot (fb_base + start, len,pgprot_val (fb_prot)); }static __ref void efi_earlycon_unmap (void *addr,unsigned long len) { +if (efi_fb) +return ; +early_memunmap (addr, len); } --Quoted 2 lines
2.24.0
--
With Best Regards,
Andy Shevchenko