How to dispatch DXE in 32-bit address in PEI-less flow ?

104 views
Skip to first unread message

John Chew

unread,
Aug 3, 2023, 2:17:46 AM8/3/23
to RISC-V Firmware Exchange, yon...@intel.com
Hi everyone,

In PEI-less flow, RAM region is allocated based on the "memory" node. 
../OvmfPkg/RiscVVirt/Sec/Memory.c:299
init_ram.png

In the device tree, the memory node is set as 0x4100_0000 ~ 0x1_0000_0000:
memory_node.png

During DXE dispatching, it will dispatch the packages in 64-bit addresses. 
VF2's JH7110 MMC driver DMA can only work with 32-bit addressing.
Thus, dispatching the driver in a 64-bit address causes the DMA to fail..
mmc_dma_fail.png

The current workaround is to set the memory node to 0x4100_0000 ~ 0x3F00_0000:
https://github.com/johnchewyy/edk2-platforms/commit/aee7012740f9adaaa972d6ade22ccb86cb72c413

Since Linux is using the same DTB as UEFI, reducing the memory range will cause errors in Linux.

I'm curious if there is a way to restrict the UEFI's RAM allocation to only utilize a 32-bit address range.
Alternatively, is there a method to enforce the use of PCD for assigning the RAM range?

Project repository:
edk2: https://github.com/johnchewyy/edk2/tree/vf2_jh7110_devel_peiless_multiarch
edk2-platform: https://github.com/johnchewyy/edk2-platforms/tree/vf2_jh7110_devel_peiless_multiarch

Log attachment:
dma_okay.txt - memory node:  0x4100_0000 ~ 0x3F00_0000
dma_hang.txt - memory node:  0x4100_0000 ~ 0x1_0000_0000

Thanks!

Regards,
John



dma_hang.txt

Tuan Phan

unread,
Aug 3, 2023, 2:26:03 AM8/3/23
to John Chew, RISC-V Firmware Exchange, yon...@intel.com
You can define UEFI top memory in 32bits range then build memory hob description as bootloader data for all above 4GB. So uefi never uses 64bits and Linux can reclaim all memory.

--
You received this message because you are subscribed to the Google Groups "RISC-V Firmware Exchange" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fw-exchange...@riscv.org.
To view this discussion on the web visit https://groups.google.com/a/riscv.org/d/msgid/fw-exchange/32c53659-c980-4af0-a361-ce05b00228e3n%40riscv.org.

John Chew

unread,
Aug 9, 2023, 1:44:08 AM8/9/23
to RISC-V Firmware Exchange, tp...@ventanamicro.com, RISC-V Firmware Exchange, yon...@intel.com, John Chew
Hi Tuan,


"define UEFI top memory in 32bits range" 
I notice that PCD "gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable" is able to limit the top address (please correct me if I'm wrong). 
But I meet some issues using this PCD. 
Before I proceed further with the investigation, is this PCD suitable to implement what you have suggested or there is another method to do it?

by any chance, do you know any example implementation that I can use for reference?

Thanks
Regards,
John

Tuan Phan

unread,
Aug 9, 2023, 2:01:05 AM8/9/23
to John Chew, RISC-V Firmware Exchange, RISC-V Firmware Exchange, yon...@intel.com, John Chew

Hi,

In Sec/SecMain.c:, search for HobConstructor then define UefiMemoryBase < 4GB

Create a DXE driver then register on ready to boot event:

 

VOID

EFIAPI

OnReadyToBootServices (

  IN EFI_EVENT Event,

  IN VOID      *Context

  )

{

  EFI_STATUS                  Status;

  UINTN                       MemoryMapSize;

  EFI_MEMORY_DESCRIPTOR       *MemoryMap, *Desc;

  UINTN                       MapKey;

  UINTN                       DescriptorSize;

  UINT32                      DescriptorVersion;

 

  EFI_PHYSICAL_ADDRESS        Addr;

  UINTN                       Idx;

  UINTN                       Pages;

 

  //

  // Close the event, so it will not be signalled again.

  //

  gBS->CloseEvent (Event);

 

  MemoryMap = NULL;

  MemoryMapSize = 0;

  Pages = 0;

 

  Status = gBS->GetMemoryMap (

                  &MemoryMapSize,

                  MemoryMap,

                  &MapKey,

                  &DescriptorSize,

                  &DescriptorVersion

                  );

  if (Status == EFI_BUFFER_TOO_SMALL) {

    Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;

    MemoryMap = AllocatePages (Pages);

 

    //

    // Get System MemoryMap

    //

    Status = gBS->GetMemoryMap (

                    &MemoryMapSize,

                    MemoryMap,

                    &MapKey,

                    &DescriptorSize,

                    &DescriptorVersion

                    );

  }

  if (EFI_ERROR (Status) || MemoryMap == NULL) {

    DEBUG ((DEBUG_ERROR, "%a: Failed to get memory map\n", __FUNCTION__));

    if (MemoryMap) {

      FreePages ((VOID *)MemoryMap, Pages);

    }

    return;

  }

 

  Desc = MemoryMap;

  for (Idx = 0; Idx < (MemoryMapSize / DescriptorSize); Idx++) {

    if (Desc->Type == EfiConventionalMemory &&

          ((Desc->PhysicalStart > MAX_UINT32) || (Desc->PhysicalStart + Desc->NumberOfPages * EFI_PAGE_SIZE) > MAX_UINT32)) {

      if (Desc->PhysicalStart > MAX_UINT32) {

        Addr = Desc->PhysicalStart;

        Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesData, Desc->NumberOfPages, &Addr);

      } else {

        Addr = 0x100000000ULL;

        Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesData, Desc->NumberOfPages - EFI_SIZE_TO_PAGES (0x100000000 - Desc->PhysicalStart), &Addr);

      }

      if (EFI_ERROR (Status)) {

        DEBUG ((DEBUG_ERROR, "%a: Failed to allocate boot service data at %llX\n", __FUNCTION__, Addr));

      }

    }

    Desc = (EFI_MEMORY_DESCRIPTOR *)((UINT64)Desc + DescriptorSize);

  }

 

  FreePages ((VOID *)MemoryMap, Pages);

}

 

If a driver allocate memory above 4GB before ReadToBoot event, you can let above code run before that point.

 

From: John Chew <yuinye...@starfivetech.com>
Date: Tuesday, August 8, 2023 at 10:44 PM
To: RISC-V Firmware Exchange <fw-ex...@riscv.org>
Cc: tp...@ventanamicro.com <tp...@ventanamicro.com>, RISC-V Firmware Exchange <fw-ex...@riscv.org>, yon...@intel.com <yon...@intel.com>, John Chew <yuinye...@starfivetech.com>
Subject: Re: How to dispatch DXE in 32-bit address in PEI-less flow ?

Hi Tuan,

"define UEFI top memory in 32bits range" 
I notice that PCD "gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable" is able to limit the top address (please correct me if I'm wrong). 
But I meet some issues using this PCD. 
Before I proceed further with the investigation, is this PCD suitable to implement what you have suggested or there is another method to do it?

by any chance, do you know any example implementation that I can use for reference?

Thanks
Regards,
John

On Thursday, August 3, 2023 at 2:26:03 PM UTC+8 tp...@ventanamicro.com wrote:

You can define UEFI top memory in 32bits range then build memory hob description as bootloader data for all above 4GB. So uefi never uses 64bits and Linux can reclaim all memory.

 

On Wed, Aug 2, 2023 at 11:17 PM John Chew <yuinye...@starfivetech.com> wrote:

Hi everyone,

In PEI-less flow, RAM region is allocated based on the "memory" node. 
../OvmfPkg/RiscVVirt/Sec/Memory.c:299



In the device tree, the memory node is set as 0x4100_0000 ~ 0x1_0000_0000:



During DXE dispatching, it will dispatch the packages in 64-bit addresses. 
VF2's JH7110 MMC driver DMA can only work with 32-bit addressing.
Thus, dispatching the driver in a 64-bit address causes the DMA to fail..



The current workaround is to set the memory node to 0x4100_0000 ~ 0x3F00_0000:
https://github.com/johnchewyy/edk2-platforms/commit/aee7012740f9adaaa972d6ade22ccb86cb72c413

Since Linux is using the same DTB as UEFI, reducing the memory range will cause errors in Linux.

I'm curious if there is a way to restrict the UEFI's RAM allocation to only utilize a 32-bit address range.
Alternatively, is there a method to enforce the use of PCD for assigning the RAM range?

Project repository:
edk2: https://github.com/johnchewyy/edk2/tree/vf2_jh7110_devel_peiless_multiarch
edk2-platform: https://github.com/johnchewyy/edk2-platforms/tree/vf2_jh7110_devel_peiless_multiarch

Log attachment:
dma_okay.txt - memory node:  0x4100_0000 ~ 0x3F00_0000
dma_hang.txt - memory node:  0x4100_0000 ~ 0x1_0000_0000

Thanks!

Regards,
John


John Chew

unread,
Aug 10, 2023, 11:47:34 PM8/10/23
to RISC-V Firmware Exchange, tp...@ventanamicro.com, RISC-V Firmware Exchange, yon...@intel.com, John Chew
Hi Tuan,

Thanks for the code example. I tried your suggestion:

" In Sec/SecMain.c:, search for HobConstructor then define UefiMemoryBase < 4GB"
address.png

I found out that the allocated page for "EfiBootServiceData" is still in 64-bit range.
Below is the memory I printed the memory for your reference.
dma_memory.png
memory_allocation.png

Thanks again!

Regards,
John

Tuan Phan

unread,
Aug 11, 2023, 12:36:33 AM8/11/23
to John Chew, RISC-V Firmware Exchange, yon...@intel.com
As i said, you need to do the code that i showed you before the failing point 

John Chew

unread,
Aug 14, 2023, 4:58:29 AM8/14/23
to RISC-V Firmware Exchange, tp...@ventanamicro.com, RISC-V Firmware Exchange, yon...@intel.com, John Chew
Hi Tuan,


"need to do the code that i showed you before the failing point "
It works!!

Thank you for your support   =)

Regards,
John

John Chew

unread,
Aug 18, 2023, 4:58:53 AM8/18/23
to RISC-V Firmware Exchange, John Chew, tp...@ventanamicro.com, RISC-V Firmware Exchange, yon...@intel.com
Hi Tuan,

I notice when my low address of RAM is set to 0x40000000 will cause my "EfiBootServiceData" to allocate to a 64-bit address.

This is the snippet of my print code:
Screenshot_3.png

Based on the log below, you can see that:
Lower RAM adrdess: 0x4000_0000 -> DMA buffer: 0x1_3F22_A000
Lower RAM address: 0x4100_0000 -> DMA buffer: 0xFFFF_F000
Also based on the log, I found out that after the new "EfiBootServiceData" page is allocated,  the new page's physical start address is located at 0xFFFF_F000
Screenshot_4.png

I'm not sure if the "reserve" memory has anything to do with this error:
Screenshot_5.png

I have also included the log for both tests log in the attachment.

Thank you =)

Regards,
John
0x4000_0000
0x4100_0000

Tuan Phan

unread,
Aug 18, 2023, 11:32:59 AM8/18/23
to John Chew, RISC-V Firmware Exchange, John Chew, RISC-V Firmware Exchange, yon...@intel.com

Hi John,

Without looking your source code, not sure what I can tell. If you can control your MMC driver then just use EDK2 API to allocate page within 4GB. It is what PCI driver does when deal with device not support above 4GB memory

 

  if (!RootBridge->DmaAbove4G ||

      ((Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0))

  {

    //

    // Limit allocations to memory below 4GB

    //

    AllocateType    = AllocateMaxAddress;

    PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(SIZE_4GB - 1);

  }

 

  Status = gBS->AllocatePages (

                  AllocateType,

                  MemoryType,

                  Pages,

                  &PhysicalAddress

                  );

 

 

From: John Chew <yuinye...@starfivetech.com>
Date: Friday, August 18, 2023 at 1:58 AM
To: RISC-V Firmware Exchange <fw-ex...@riscv.org>
Cc: John Chew <yuinye...@starfivetech.com>, tp...@ventanamicro.com <tp...@ventanamicro.com>, RISC-V Firmware Exchange <fw-ex...@riscv.org>, yon...@intel.com <yon...@intel.com>
Subject: Re: How to dispatch DXE in 32-bit address in PEI-less flow ?

Hi Tuan,


I notice when my low address of RAM is set to 0x40000000 will cause my "EfiBootServiceData" to allocate to a 64-bit address.

This is the snippet of my print code:



Based on the log below, you can see that:
Lower RAM adrdess: 0x4000_0000 -> DMA buffer: 0x1_3F22_A000
Lower RAM address: 0x4100_0000 -> DMA buffer: 0xFFFF_F000
Also based on the log, I found out that after the new "EfiBootServiceData" page is allocated,  the new page's physical start address is located at 0xFFFF_F000



I'm not sure if the "reserve" memory has anything to do with this error:



I have also included the log for both tests log in the attachment.

Thank you =)

Regards,
John

On Monday, August 14, 2023 at 4:58:29 PM UTC+8 John Chew wrote:

Hi Tuan,

"need to do the code that i showed you before the failing point "
It works!!

Thank you for your support   =)

Regards,
John

On Friday, August 11, 2023 at 12:36:33 PM UTC+8 tp...@ventanamicro.com wrote:

As i said, you need to do the code that i showed you before the failing point 

 

On Thu, Aug 10, 2023 at 8:47 PM John Chew <yuinye...@starfivetech.com> wrote:

Hi Tuan,

Thanks for the code example. I tried your suggestion:
" In Sec/SecMain.c:, search for HobConstructor then define UefiMemoryBase < 4GB"



I found out that the allocated page for "EfiBootServiceData" is still in 64-bit range.
Below is the memory I printed the memory for your reference.




Thanks again!

Regards,
John

Image removed by sender.



In the device tree, the memory node is set as 0x4100_0000 ~ 0x1_0000_0000:

Image removed by sender.



During DXE dispatching, it will dispatch the packages in 64-bit addresses. 
VF2's JH7110 MMC driver DMA can only work with 32-bit addressing.
Thus, dispatching the driver in a 64-bit address causes the DMA to fail..

Image removed by sender.



The current workaround is to set the memory node to 0x4100_0000 ~ 0x3F00_0000:
https://github.com/johnchewyy/edk2-platforms/commit/aee7012740f9adaaa972d6ade22ccb86cb72c413

Since Linux is using the same DTB as UEFI, reducing the memory range will cause errors in Linux.

I'm curious if there is a way to restrict the UEFI's RAM allocation to only utilize a 32-bit address range.
Alternatively, is there a method to enforce the use of PCD for assigning the RAM range?

Project repository:
edk2: https://github.com/johnchewyy/edk2/tree/vf2_jh7110_devel_peiless_multiarch
edk2-platform: https://github.com/johnchewyy/edk2-platforms/tree/vf2_jh7110_devel_peiless_multiarch

Log attachment:
dma_okay.txt - memory node:  0x4100_0000 ~ 0x3F00_0000
dma_hang.txt - memory node:  0x4100_0000 ~ 0x1_0000_0000

Thanks!

Regards,
John

--
You received this message because you are subscribed to the Google Groups "RISC-V Firmware Exchange" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fw-exchange...@riscv.org.
To view this discussion on the web visit https://groups.google.com/a/riscv.org/d/msgid/fw-exchange/32c53659-c980-4af0-a361-ce05b00228e3n%40riscv.org.

--
You received this message because you are subscribed to the Google Groups "RISC-V Firmware Exchange" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fw-exchange...@riscv.org.

John Chew

unread,
Aug 23, 2023, 3:03:44 AM8/23/23
to RISC-V Firmware Exchange, tp...@ventanamicro.com, John Chew, RISC-V Firmware Exchange, yon...@intel.com
Hi Tuan,

Thanks for the PCIe example. It works that way. 

Alternatively, allocating all "EfiConventionalMemory" to "EfiBootServicesData" (as shown in the first code example earlier),
at the early stage of DXE dispatching also does the trick.

Thank you! 

Regards,
John
Reply all
Reply to author
Forward
0 new messages