[edk2-devel] [PATCH v2 2/6] OvmfPkg/AmdSev: add Grub Firmware Volume Package

Laszlo Ersek lersek at redhat.com
Wed Nov 25 19:08:02 UTC 2020


On 11/25/20 19:35, Laszlo Ersek wrote:
> On 11/25/20 18:09, James Bottomley wrote:
>> On Wed, 2020-11-25 at 08:02 -0800, James Bottomley wrote:
>>> On Wed, 2020-11-25 at 15:01 +0100, Laszlo Ersek wrote:
>>>> This upgrade gave me kernel 5.8.18-100.fc31.x86_64 in the guest --
>>>> and this one does *not* crash. From your boot log below, I see your
>>>> guest kernel is 5.5.0; I suggest upgrading it.
>>>
>>> Heh, that's easier said than done ... I always make my encrypted
>>> images too small to upgrade a kernel easily.  Anyway, after doing the
>>> remove and add stuff dance, I finally got it upgraded to the latest
>>> debian testing linux-image-5.8.0-3 it's still crashing although with
>>> a slightly different traceback.  It looks like there might be
>>> something additional in the fedora 5.8 kernel that fixes this.  I'm
>>> going to try out upstream kernels next.
>>
>> I've got the upstream kernel booting through OVMF with a qemu -kernel
>> command line.  I also have a fix: it's not to delete the dummy variable
>> which was part of the ancient x86 anti bricking code (which is also why
>> arm64 doesn't have the problem).
>>
>> If you remove the set variable in arch/x86/platform/efi/quirks.c:
>>
>> /*
>>  * Deleting the dummy variable which kicks off garbage collection
>> */
>> void efi_delete_dummy_variable(void)
>> {
>> 	efi.set_variable_nonblocking((efi_char16_t *)efi_dummy_name,
>> 				     &EFI_DUMMY_GUID,
>> 				     EFI_VARIABLE_NON_VOLATILE |
>> 				     EFI_VARIABLE_BOOTSERVICE_ACCESS |
>> 				     EFI_VARIABLE_RUNTIME_ACCESS, 0, NULL);
>> }
>>
>> The kernel will boot.  I'm not sure why we have this deletion
>> unconditionally in efi_enter_virtual_mode, but removing the call with
>> the patch below allows the kernel to boot.
> 
> I think commit 2ecb7402cfc7 ("efi/x86: Do not clean dummy variable in
> kexec path", 2019-10-07) is related (part of v5.4), but it's not
> sufficient to prevent the boot crash. (That removal only covered the
> kexec path, and not the normal boot path.)
> 
>>
>> However, once the kernel has booted, any attempt to write to an EFI
>> variable results in this:
>>
>> [  975.440240] [Firmware Bug]: Page fault caused by firmware at PA: 0x7e450020
>>
>> And then the efi runtime gets disabled.
> 
> Blech, that doesn't look good. We still get a page fault somewhere in
> the firmware, it just doesn't kill the kernel outright. That kind of
> suggests the crash on the boot path *is* firmware-originated, it's just
> that the kernel is unable to mask the problem that early.

Actually, I do think we have a bug in the firmware. I need to verify it
(and if verification confirms it, to send a patch for it). Consider the
following snippet in file
"MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c", function
RegisterVariablePolicy():

    // Reallocate and copy the table.
    NewTable = AllocatePool( NewSize );
    if (NewTable == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
    CopyMem( NewTable, mPolicyTable, mCurrentTableUsage );
    mCurrentTableSize = NewSize;
    if (mPolicyTable != NULL) {
      FreePool( mPolicyTable );
    }
    mPolicyTable = NewTable;


* In the SMM build of OVMF, this code is linked (via
"MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf") into the
following SMM driver:

  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf

For that module (well, for SMM drivers in general), the AllocatePool()
function comes from the following MemoryAllocationLib instance:

  MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf

and so the AllocatePool() call ultimately boils down to allocating *SMRAM*:

  gSmst->SmmAllocatePool()

Which is fine.


* However, in the non-SMM build, the same code snippet is linked (via
"MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf")
into the following driver:

  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf

In this module (well, in runtime DXE drivers in general), the
AllocatePool() call function comes from the following
MemoryAllocationLib instance:

  MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf

And that is *wrong*. Because there, AllocatePool() allocates Boot
Services Data type memory, via

  gBS->AllocatePool() *plus* "EfiBootServicesData"

Therefore, even though VariablePolicyLibVirtualAddressCallback() in file
"MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c"
attempts to convert "mPolicyTable" to a runtime virtual address, in the
SMM-less build, that conversion fails -- the original memory that the
pointer points at, pre-conversion, is not runtime, but boot time memory.


The fix *should be* to call AllocateRuntimePool() from the
MemoryAllocationLib class. In the SMM instance, that will make no
difference; compare, in
"MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c":

VOID *
EFIAPI
AllocatePool (
  IN UINTN  AllocationSize
  )
{
  return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
}

VOID *
EFIAPI
AllocateRuntimePool (
  IN UINTN  AllocationSize
  )
{
  return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
}

The InternalAllocatePool() calls are identical, in the SMM instance.


Whereas in the UEFI instance, in
"MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c", it does
make a difference; compare:

VOID *
EFIAPI
AllocatePool (
  IN UINTN  AllocationSize
  )
{
  return InternalAllocatePool (EfiBootServicesData, AllocationSize);
}

VOID *
EFIAPI
AllocateRuntimePool (
  IN UINTN  AllocationSize
  )
{
  return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
}

The "MemoryType" parameter of InternalAllocatePool(), which gets
forwarded to gBS->AllocatePool(), changes from "EfiBootServicesData" to
"EfiRuntimeServicesData".

Let me test this.

(BTW I see some more pool allocations in
"MdeModulePkg/Library/VariablePolicyHelperLib" to... I guess I'll have
to check those as well.)

Thanks
Laszlo



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#67997): https://edk2.groups.io/g/devel/message/67997
Mute This Topic: https://groups.io/mt/78455898/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list