[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH RFC] EFI: allow retry of ExitBootServices() call
On Fri, Nov 14, 2014 at 12:37:30PM +0000, Jan Beulich wrote: > The specification is kind of vague under what conditions > ExitBootServices() may legitimately fail, requiring the OS loader to > retry: > > "If MapKey value is incorrect, ExitBootServices() returns > EFI_INVALID_PARAMETER and GetMemoryMap() with ExitBootServices() must > be called again. Firmware implementation may choose to do a partial > shutdown of the boot services during the first call to > ExitBootServices(). EFI OS loader should not make calls to any boot > service function other then GetMemoryMap() after the first call to > ExitBootServices()." > > While our code guarantees the map key to be valid, there are systems > where a firmware internal notification sent while processing > ExitBootServices() reportedly results in changes to the memory map. s/reportedly/in fact/ > In that case, make a best effort second try: Avoid any boot service > calls other than the two named above, with the possible exception of > error paths. Those aren't a problem, since if we end up needing to > retry, we're hosed when something goes wrong as much as if we didn't > make the retry attempt. > > For x86, a minimal adjustment to efi_arch_process_memory_map() is > needed for it to cope with potentially being called a second time. Wow. Talk about timing. We saw this and were going to see doing something similar. > > For arm64, while efi_process_memory_map_bootinfo() is easy to verify > that it can safely be called more than once without violating spec > constraints, it's not so obvious for fdt_add_uefi_nodes(), hence a > step by step approach: > - deletion of memory nodes and memory reserve map entries: the 2nd pass > shouldn't find any as the 1st one deleted them all, > - a "chosen" node should be found as it got added in the 1st pass, > - the various "linux,uefi-*" nodes all got added during the 1st pass > and hence only their contents may get updated. > > Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> > > --- a/xen/arch/x86/efi/efi-boot.h > +++ b/xen/arch/x86/efi/efi-boot.h > @@ -140,7 +140,7 @@ static void __init efi_arch_process_memo > > /* Populate E820 table and check trampoline area availability. */ > e = e820map - 1; > - for ( i = 0; i < map_size; i += desc_size ) > + for ( e820nr = i = 0; i < map_size; i += desc_size ) > { > EFI_MEMORY_DESCRIPTOR *desc = map + i; > u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT; > --- a/xen/common/efi/boot.c > +++ b/xen/common/efi/boot.c > @@ -703,7 +703,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY > EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL; > EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info; > union string section = { NULL }, name; > - bool_t base_video = 0; > + bool_t base_video = 0, retry; > char *option_str; > bool_t use_cfg_file; > > @@ -1051,17 +1051,23 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY > if ( !efi_memmap ) > blexit(L"Unable to allocate memory for EFI memory map"); > > - status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key, > - &efi_mdesc_size, &mdesc_ver); > - if ( EFI_ERROR(status) ) > - PrintErrMesg(L"Cannot obtain memory map", status); > + for ( retry = 0; ; retry = 1 ) > + { > + status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key, > + &efi_mdesc_size, &mdesc_ver); > + if ( EFI_ERROR(status) ) > + PrintErrMesg(L"Cannot obtain memory map", status); > > - efi_arch_process_memory_map(SystemTable, efi_memmap, efi_memmap_size, > - efi_mdesc_size, mdesc_ver); > + efi_arch_process_memory_map(SystemTable, efi_memmap, efi_memmap_size, > + efi_mdesc_size, mdesc_ver); > > - efi_arch_pre_exit_boot(); > + efi_arch_pre_exit_boot(); > + > + status = efi_bs->ExitBootServices(ImageHandle, map_key); > + if ( status != EFI_INVALID_PARAMETER || retry ) > + break; > + } Any reason for just doing the loop at max twice? Could we iterate more than those (say forever?) with an printk at suitable intervals to notify the user? > > - status = efi_bs->ExitBootServices(ImageHandle, map_key); > if ( EFI_ERROR(status) ) > PrintErrMesg(L"Cannot exit boot services", status); > > > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |