git: 1b5e5ff68c2b - main - xen/pvh: fix initialization of environment
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 02 Aug 2024 10:42:55 UTC
The branch main has been updated by royger: URL: https://cgit.FreeBSD.org/src/commit/?id=1b5e5ff68c2bafae55a5adab42f22039bbbce59c commit 1b5e5ff68c2bafae55a5adab42f22039bbbce59c Author: Roger Pau Monné <royger@FreeBSD.org> AuthorDate: 2024-07-18 08:14:28 +0000 Commit: Roger Pau Monné <royger@FreeBSD.org> CommitDate: 2024-08-02 10:41:52 +0000 xen/pvh: fix initialization of environment Xen PVH entry point requires to modify the environment provided by the boot loader, so that the ACPI RSDP is re-written to use the Xen generated RSDP instead of the native one. The current logic in the PVH entry point reserves a single page (4K) in order to copy the contents of the environment passed from the boot loader, so that the bootloader provided "acpi.rsdp" is dropped and a Xen specific one is added afterwards. This however doesn't scale well, as it's possible for the environment to be bigger than 4K. Bumping the buffer, or attempting to peek at the size of the metadata all seem to just add more complexity to a sensitive path. Instead introduce a new ACPI hook that allows setting the RSDP address directly, and use it from the PVH entry point to set the position of the Xen generated RSDP. This allows to reduce the logic in the PVH metadata processing, as there's no need to parse and filter the bootloader provided environment. Note that modifying the environment blob in-place is likely to not work. The RSDP address is provided as a string, it's possible the new RSDP location is higher than the current one, and the string with the new location would overrun the space used by the previous one. Sponsored by: Cloud Software Group PR: 277200 MFC: 3 days Reviewed by: markj kib Differential revision: https://reviews.freebsd.org/D46089 --- sys/x86/acpica/OsdEnvironment.c | 12 +++++-- sys/x86/include/acpica_machdep.h | 2 ++ sys/x86/xen/pv.c | 74 +++++++--------------------------------- 3 files changed, 25 insertions(+), 63 deletions(-) diff --git a/sys/x86/acpica/OsdEnvironment.c b/sys/x86/acpica/OsdEnvironment.c index c9dd3d0560cc..55954f8336fa 100644 --- a/sys/x86/acpica/OsdEnvironment.c +++ b/sys/x86/acpica/OsdEnvironment.c @@ -77,14 +77,22 @@ acpi_get_root_from_memory(void) return (0); } +void +acpi_set_root(vm_paddr_t addr) +{ + + KASSERT(acpi_root_phys == 0, ("ACPI root pointer already set")); + acpi_root_phys = addr; +} + ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer(void) { if (acpi_root_phys == 0) { - acpi_root_phys = acpi_get_root_from_loader(); + acpi_set_root(acpi_get_root_from_loader()); if (acpi_root_phys == 0) - acpi_root_phys = acpi_get_root_from_memory(); + acpi_set_root(acpi_get_root_from_memory()); } return (acpi_root_phys); diff --git a/sys/x86/include/acpica_machdep.h b/sys/x86/include/acpica_machdep.h index b4811e4bd30c..2592b47ae1c1 100644 --- a/sys/x86/include/acpica_machdep.h +++ b/sys/x86/include/acpica_machdep.h @@ -84,6 +84,8 @@ void madt_parse_interrupt_values(void *entry, extern int madt_found_sci_override; extern int (*apei_nmi)(void); +void acpi_set_root(vm_paddr_t addr); + #endif /* _KERNEL */ #endif /* __ACPICA_MACHDEP_H__ */ diff --git a/sys/x86/xen/pv.c b/sys/x86/xen/pv.c index 0e6492b124b8..388543d64254 100644 --- a/sys/x86/xen/pv.c +++ b/sys/x86/xen/pv.c @@ -60,6 +60,7 @@ #include <machine/_inttypes.h> #include <machine/intr_machdep.h> +#include <x86/acpica_machdep.h> #include <x86/apicvar.h> #include <x86/init.h> #include <machine/pc/bios.h> @@ -157,7 +158,6 @@ hammer_time_xen(vm_paddr_t start_info_paddr) { struct hvm_modlist_entry *mod; uint64_t physfree; - char *kenv; start_info = (struct hvm_start_info *)(start_info_paddr + KERNBASE); if (start_info->magic != XEN_HVM_START_MAGIC_VALUE) { @@ -196,15 +196,6 @@ hammer_time_xen(vm_paddr_t start_info_paddr) PAGE_SIZE), physfree); } - /* - * Init a static kenv using a free page. The contents will be filled - * from the parse_preload_data hook. - */ - kenv = (void *)(physfree + KERNBASE); - physfree += PAGE_SIZE; - bzero_early(kenv, PAGE_SIZE); - init_static_kenv(kenv, PAGE_SIZE); - /* Set the hooks for early functions that diverge from bare metal */ init_ops = xen_pvh_init_ops; hvm_start_flags = start_info->flags; @@ -215,52 +206,6 @@ hammer_time_xen(vm_paddr_t start_info_paddr) /*-------------------------------- PV specific -------------------------------*/ -/* - * When booted as a PVH guest FreeBSD needs to avoid using the RSDP address - * hint provided by the loader because it points to the native set of ACPI - * tables instead of the ones crafted by Xen. The acpi.rsdp env variable is - * removed from kenv if present, and a new acpi.rsdp is added to kenv that - * points to the address of the Xen crafted RSDP. - */ -static bool reject_option(const char *option) -{ - static const char *reject[] = { - "acpi.rsdp", - }; - unsigned int i; - - for (i = 0; i < nitems(reject); i++) - if (strncmp(option, reject[i], strlen(reject[i])) == 0) - return (true); - - return (false); -} - -static void -xen_pvh_set_env(char *env, bool (*filter)(const char *)) -{ - char *option; - - if (env == NULL) - return; - - option = env; - while (*option != 0) { - char *value; - - if (filter != NULL && filter(option)) { - option += strlen(option) + 1; - continue; - } - - value = option; - option = strsep(&value, "="); - if (kern_setenv(option, value) != 0 && isxen()) - xc_printf("unable to add kenv %s=%s\n", option, value); - option = value + strlen(value) + 1; - } -} - #ifdef DDB /* * The way Xen loads the symtab is different from the native boot loader, @@ -313,7 +258,6 @@ xen_pvh_parse_preload_data(uint64_t modulep) vm_ooffset_t off; vm_paddr_t metadata; char *envp; - char acpi_rsdp[19]; TSENTER(); if (start_info->modlist_paddr != 0) { @@ -379,13 +323,18 @@ xen_pvh_parse_preload_data(uint64_t modulep) envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); if (envp != NULL) envp += off; - xen_pvh_set_env(envp, reject_option); + init_static_kenv(envp, 0); if (MD_FETCH(kmdp, MODINFOMD_EFI_MAP, void *) != NULL) strlcpy(bootmethod, "UEFI", sizeof(bootmethod)); else strlcpy(bootmethod, "BIOS", sizeof(bootmethod)); } else { + static char kenv_buffer[PAGE_SIZE]; + + /* Provide a static kenv so the command line can be parsed. */ + init_static_kenv(kenv_buffer, sizeof(kenv_buffer)); + /* Parse the extra boot information given by Xen */ if (start_info->cmdline_paddr != 0) boot_parse_cmdline_delim( @@ -397,9 +346,12 @@ xen_pvh_parse_preload_data(uint64_t modulep) boothowto |= boot_env_to_howto(); - snprintf(acpi_rsdp, sizeof(acpi_rsdp), "%#" PRIx64, - start_info->rsdp_paddr); - kern_setenv("acpi.rsdp", acpi_rsdp); + /* + * When booted as a PVH guest FreeBSD must not use the RSDP address + * hint provided by the loader because it points to the native set of + * ACPI tables instead of the ones crafted by Xen. + */ + acpi_set_root(start_info->rsdp_paddr); #ifdef DDB xen_pvh_parse_symtab();