git: 027b66d64b54 - main - x86/xen: do video console fixup as part of early initialization
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 22 Feb 2024 10:31:25 UTC
The branch main has been updated by royger: URL: https://cgit.FreeBSD.org/src/commit/?id=027b66d64b547b2133c11b596a7e308ea8c83ccb commit 027b66d64b547b2133c11b596a7e308ea8c83ccb Author: Roger Pau Monné <royger@FreeBSD.org> AuthorDate: 2024-02-02 10:29:57 +0000 Commit: Roger Pau Monné <royger@FreeBSD.org> CommitDate: 2024-02-22 10:08:05 +0000 x86/xen: do video console fixup as part of early initialization When FreeBSD is running as dom0 the video console metadata provided by the bootloader might not be accurate, as Xen has very likely taken over the console and possibly changed the mode. Adjust the video console information in the kernel metadata as part of early Xen initialization. Sponsored by: Cloud Software Group Reviewed by: imp Differential revision: https://reviews.freebsd.org/D43934 --- sys/x86/xen/hvm.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ sys/x86/xen/pv.c | 83 ---------------------------------------------------- 2 files changed, 87 insertions(+), 83 deletions(-) diff --git a/sys/x86/xen/hvm.c b/sys/x86/xen/hvm.c index 9dc9360d719c..85f274175ac6 100644 --- a/sys/x86/xen/hvm.c +++ b/sys/x86/xen/hvm.c @@ -30,6 +30,7 @@ #include <sys/param.h> #include <sys/bus.h> #include <sys/kernel.h> +#include <sys/linker.h> #include <sys/malloc.h> #include <sys/proc.h> #include <sys/smp.h> @@ -45,6 +46,7 @@ #include <machine/cpufunc.h> #include <machine/cpu.h> #include <machine/md_var.h> +#include <machine/metadata.h> #include <machine/smp.h> #include <x86/apicreg.h> @@ -246,6 +248,87 @@ map_shared_info(void) return (rc); } +static void +fixup_console(void) +{ + struct xen_platform_op op = { + .cmd = XENPF_get_dom0_console, + }; + xenpf_dom0_console_t *console = &op.u.dom0_console; + union { + struct efi_fb efi; + struct vbe_fb vbe; + } *fb = NULL; + int size; + caddr_t kmdp; + + kmdp = preload_search_by_type("elf kernel"); + if (kmdp == NULL) + kmdp = preload_search_by_type("elf64 kernel"); + if (kmdp == NULL) { + xc_printf("Unable to find kernel metadata\n"); + return; + } + + size = HYPERVISOR_platform_op(&op); + if (size < 0) { + xc_printf("Failed to get video console info: %d\n", size); + return; + } + + switch (console->video_type) { + case XEN_VGATYPE_VESA_LFB: + fb = (__typeof__ (fb))preload_search_info(kmdp, + MODINFO_METADATA | MODINFOMD_VBE_FB); + + if (fb == NULL) { + xc_printf("No VBE FB in kernel metadata\n"); + return; + } + + _Static_assert(offsetof(struct vbe_fb, fb_bpp) == + offsetof(struct efi_fb, fb_mask_reserved) + + sizeof(fb->efi.fb_mask_reserved), + "Bad structure overlay\n"); + fb->vbe.fb_bpp = console->u.vesa_lfb.bits_per_pixel; + /* FALLTHROUGH */ + case XEN_VGATYPE_EFI_LFB: + if (fb == NULL) { + fb = (__typeof__ (fb))preload_search_info(kmdp, + MODINFO_METADATA | MODINFOMD_EFI_FB); + if (fb == NULL) { + xc_printf("No EFI FB in kernel metadata\n"); + return; + } + } + + fb->efi.fb_addr = console->u.vesa_lfb.lfb_base; + if (size > + offsetof(xenpf_dom0_console_t, u.vesa_lfb.ext_lfb_base)) + fb->efi.fb_addr |= + (uint64_t)console->u.vesa_lfb.ext_lfb_base << 32; + fb->efi.fb_size = console->u.vesa_lfb.lfb_size << 16; + fb->efi.fb_height = console->u.vesa_lfb.height; + fb->efi.fb_width = console->u.vesa_lfb.width; + fb->efi.fb_stride = (console->u.vesa_lfb.bytes_per_line << 3) / + console->u.vesa_lfb.bits_per_pixel; +#define FBMASK(c) \ + ((~0u << console->u.vesa_lfb.c ## _pos) & \ + (~0u >> (32 - console->u.vesa_lfb.c ## _pos - \ + console->u.vesa_lfb.c ## _size))) + fb->efi.fb_mask_red = FBMASK(red); + fb->efi.fb_mask_green = FBMASK(green); + fb->efi.fb_mask_blue = FBMASK(blue); + fb->efi.fb_mask_reserved = FBMASK(rsvd); +#undef FBMASK + break; + + default: + xc_printf("Video console type unsupported\n"); + return; + } +} + /* Early initialization when running as a Xen guest. */ void xen_early_init(void) @@ -273,6 +356,10 @@ xen_early_init(void) vm_guest = VM_GUEST_VM; return; } + + if (xen_initial_domain()) + /* Fixup video console information in case Xen changed the mode. */ + fixup_console(); } static void diff --git a/sys/x86/xen/pv.c b/sys/x86/xen/pv.c index 515e5c58d304..e33fa41c83d7 100644 --- a/sys/x86/xen/pv.c +++ b/sys/x86/xen/pv.c @@ -319,87 +319,6 @@ xen_pvh_parse_symtab(void) } #endif -static void -fixup_console(void) -{ - struct xen_platform_op op = { - .cmd = XENPF_get_dom0_console, - }; - xenpf_dom0_console_t *console = &op.u.dom0_console; - union { - struct efi_fb efi; - struct vbe_fb vbe; - } *fb = NULL; - int size; - caddr_t kmdp; - - kmdp = preload_search_by_type("elf kernel"); - if (kmdp == NULL) - kmdp = preload_search_by_type("elf64 kernel"); - if (kmdp == NULL) { - xc_printf("Unable to find kernel metadata\n"); - return; - } - - size = HYPERVISOR_platform_op(&op); - if (size < 0) { - xc_printf("Failed to get video console info: %d\n", size); - return; - } - - switch (console->video_type) { - case XEN_VGATYPE_VESA_LFB: - fb = (__typeof__ (fb))preload_search_info(kmdp, - MODINFO_METADATA | MODINFOMD_VBE_FB); - - if (fb == NULL) { - xc_printf("No VBE FB in kernel metadata\n"); - return; - } - - _Static_assert(offsetof(struct vbe_fb, fb_bpp) == - offsetof(struct efi_fb, fb_mask_reserved) + - sizeof(fb->efi.fb_mask_reserved), - "Bad structure overlay\n"); - fb->vbe.fb_bpp = console->u.vesa_lfb.bits_per_pixel; - /* FALLTHROUGH */ - case XEN_VGATYPE_EFI_LFB: - if (fb == NULL) { - fb = (__typeof__ (fb))preload_search_info(kmdp, - MODINFO_METADATA | MODINFOMD_EFI_FB); - if (fb == NULL) { - xc_printf("No EFI FB in kernel metadata\n"); - return; - } - } - - fb->efi.fb_addr = console->u.vesa_lfb.lfb_base; - if (size > - offsetof(xenpf_dom0_console_t, u.vesa_lfb.ext_lfb_base)) - fb->efi.fb_addr |= - (uint64_t)console->u.vesa_lfb.ext_lfb_base << 32; - fb->efi.fb_size = console->u.vesa_lfb.lfb_size << 16; - fb->efi.fb_height = console->u.vesa_lfb.height; - fb->efi.fb_width = console->u.vesa_lfb.width; - fb->efi.fb_stride = (console->u.vesa_lfb.bytes_per_line << 3) / - console->u.vesa_lfb.bits_per_pixel; -#define FBMASK(c) \ - ((~0u << console->u.vesa_lfb.c ## _pos) & \ - (~0u >> (32 - console->u.vesa_lfb.c ## _pos - \ - console->u.vesa_lfb.c ## _size))) - fb->efi.fb_mask_red = FBMASK(red); - fb->efi.fb_mask_green = FBMASK(green); - fb->efi.fb_mask_blue = FBMASK(blue); - fb->efi.fb_mask_reserved = FBMASK(rsvd); -#undef FBMASK - break; - - default: - xc_printf("Video console type unsupported\n"); - return; - } -} - static caddr_t xen_pvh_parse_preload_data(uint64_t modulep) { @@ -479,8 +398,6 @@ xen_pvh_parse_preload_data(uint64_t modulep) strlcpy(bootmethod, "UEFI", sizeof(bootmethod)); else strlcpy(bootmethod, "BIOS", sizeof(bootmethod)); - - fixup_console(); } else { /* Parse the extra boot information given by Xen */ if (start_info->cmdline_paddr != 0)