[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v6] Preserve the EFI System Resource Table for dom0



On Thu, May 19, 2022 at 12:32:33PM +0200, Jan Beulich wrote:
> On 18.05.2022 19:32, Demi Marie Obenour wrote:
> > @@ -567,6 +587,39 @@ static int __init efi_check_dt_boot(const 
> > EFI_LOADED_IMAGE *loaded_image)
> >  }
> >  #endif
> >  
> > +static UINTN __initdata esrt = EFI_INVALID_TABLE_ADDR;
> 
> Just out of curiosity: It's an arbitrary choice to use this initializer,
> i.e. no initializer (and hence zero) would do as well (with ...

That is correct.  I chose EFI_INVALID_TABLE_ADDR because it seemed meant
for this purpose.

> > +static size_t __init get_esrt_size(const EFI_MEMORY_DESCRIPTOR *desc)
> > +{
> > +    size_t available_len, len;
> > +    const UINTN physical_start = desc->PhysicalStart;
> > +    const EFI_SYSTEM_RESOURCE_TABLE *esrt_ptr;
> > +
> > +    len = desc->NumberOfPages << EFI_PAGE_SHIFT;
> > +    if ( esrt == EFI_INVALID_TABLE_ADDR )
> 
> ... an adjustment here, of course)?
> 
> > +        return 0;
> > +    if ( physical_start > esrt || esrt - physical_start >= len )
> > +        return 0;
> > +    /*
> > +     * The specification requires EfiBootServicesData, but accept
> > +     * EfiRuntimeServicesData, which is a more logical choice.
> > +     */
> > +    if ( (desc->Type != EfiRuntimeServicesData) &&
> > +         (desc->Type != EfiBootServicesData) )
> > +        return 0;
> > +    available_len = len - (esrt - physical_start);
> > +    if ( available_len <= offsetof(EFI_SYSTEM_RESOURCE_TABLE, Entries) )
> > +        return 0;
> > +    available_len -= offsetof(EFI_SYSTEM_RESOURCE_TABLE, Entries);
> > +    esrt_ptr = (const EFI_SYSTEM_RESOURCE_TABLE *)esrt;
> > +    if ( esrt_ptr->FwResourceVersion != 
> > EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION ||
> 
> Nit (style): Overlong line.

Where is the best place to split this?
EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION is a rather long
identifier.

> > +         !esrt_ptr->FwResourceCount )
> > +        return 0;
> > +    if ( esrt_ptr->FwResourceCount > available_len / 
> > sizeof(esrt_ptr->Entries[0]) )
> > +        return 0;
> > +    return esrt_ptr->FwResourceCount * sizeof(esrt_ptr->Entries[0]);
> > +}
> 
> Nit (style again): We generally put a blank line ahead of a function's
> main return statement.

Will fix in v7.

> > @@ -1067,6 +1122,46 @@ static void __init efi_exit_boot(EFI_HANDLE 
> > ImageHandle, EFI_SYSTEM_TABLE *Syste
> >      if ( !efi_memmap )
> >          blexit(L"Unable to allocate memory for EFI memory map");
> >  
> > +    efi_memmap_size = info_size;
> 
> I don't think this global needs setting here, yet? The local will
> do just fine here, likely yielding smaller code. But I realize that's
> connected to how you did your change vs what I was expecting you to
> do (see below).
> 
> > +    status = SystemTable->BootServices->GetMemoryMap(&efi_memmap_size,
> > +                                                     efi_memmap, &map_key,
> > +                                                     &efi_mdesc_size,
> > +                                                     &mdesc_ver);
> > +    if ( EFI_ERROR(status) )
> > +        PrintErrMesg(L"Cannot obtain memory map", status);
> > +
> > +    /* Try to obtain the ESRT.  Errors are not fatal. */
> > +    for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
> > +    {
> > +        /*
> > +         * ESRT needs to be moved to memory of type EfiRuntimeServicesData
> > +         * so that the memory it is in will not be used for other purposes.
> > +         */
> > +        void *new_esrt = NULL;
> > +        size_t esrt_size = get_esrt_size(efi_memmap + i);
> > +
> > +        if ( !esrt_size )
> > +            continue;
> > +        if ( ((EFI_MEMORY_DESCRIPTOR *)(efi_memmap + i))->Type ==
> > +             EfiRuntimeServicesData )
> > +            break; /* ESRT already safe from reuse */
> > +        status = efi_bs->AllocatePool(EfiRuntimeServicesData, esrt_size,
> > +                                      &new_esrt);
> 
> I should have re-raised the earlier voiced concern when reviewing v5 (or
> maybe already v4), and I'm sorry for not having paid close enough
> attention: This may add up to two more entries in the memory map (if an
> entry is split and its middle part is used; of course with an unusual
> implementation there could be even more of a growth). Yet below your
> addition, before obtaining the final memory map, you don't re- obtain
> (and re-increase) the size needed. As to (re-)increase: In fact, prior
> to the allocation you do there shouldn't be a need to bump the space by
> 8 extra entries. That's a safety measure only for possible allocations
> happening across ExitBootServices().
> 
> And yes, in earlier versions you had
> 
> -    info_size += 8 * efi_mdesc_size;
> +    info_size += 8 * (efi_mdesc_size + 1);
> 
> there, but that's not what would be needed anyway (if trying to avoid
> a 2nd pass of establishing the needed size). Instead in such an event
> you need to bump 8 to 10 (or at least 9, when assuming that normally it
> wouldn't be the middle part of a new range which would be used, but
> rather the leading or trailing one).
> 
> While I'd be okay with addressing the two nits above while committing,
> this allocation size aspect first wants settling on. Personally I'd
> prefer the more involved solution, but I'd be okay with merely
> bumping the 8 (plus the addition of a suitable comment, explaining
> the now multiple [two] constituent parts of a seemingly arbitrary
> number). If you want to go this easier route, I guess I could also
> make that adjustment while committing (and adding my R-b).

I would prefer the more involved solution too, but I am not quite sure
how to implement it.  Should Xen call GetMemoryMap() in a loop, retrying
as long as it returns EFI_BUFFER_TOO_SMALL?  If I do get
EFI_BUFFER_TOO_SMALL, how should I allocate memory for the new buffer?
Should I ask ebmalloc() to provide all remaining memory, and then tell
it how much was actually used?

Once I understand how to allocate the memory for the new memory map, and
where to split the long line mentioned above, I will send a v7.

-- 
Sincerely,
Demi Marie Obenour (she/her/hers)
Invisible Things Lab

Attachment: signature.asc
Description: PGP signature


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.