On 06/23/16 16:19, Achin Gupta wrote:
> Hi Laszlo,
> 
> On Wed, Jun 22, 2016 at 09:56:11PM +0200, Laszlo Ersek wrote:
>> On 06/22/16 20:53, Achin Gupta wrote:
>>> Hi All,
>>>
>>> I having some trouble trying an experiment on the AARCH64 Base FVP with 
>>> UEFI and
>>> ARM Trusted Firmware. There is a buffer that is allocated by the latter in 
>>> DRAM
>>> with TZC-400 attributes that allow non-secure access. Its extents are made
>>> available to a UEFI DXE driver through an SMC. AFAIU, it should be added to 
>>> the
>>> UEFI memory map/EL2 translation tables and subsequently allocated before it 
>>> can
>>> be used.
>>>
>>> To add it to the memory map, I successfully call AddMemorySpace() GCD 
>>> service as
>>> follows:
>>>
>>>  Status = gDS->AddMemorySpace(EfiGcdMemoryTypeSystemMemory,
>>>                               (EFI_PHYSICAL_ADDRESS) mNsBufferAddress,
>>>                               mNsBufferMaxSize,
>>>                               EFI_MEMORY_WB | EFI_MEMORY_XP);
>>>
>>> To allocate this buffer, I call AllocateMemorySpace GCD service immediately
>>> after AddMemorySpace() as follows:
>>>
>>> Status = gDS->AllocateMemorySpace(EfiGcdAllocateAddress,
>>>                                   EfiGcdMemoryTypeSystemMemory,
>>>                                   EFI_PAGE_SHIFT,
>>>                                   mNsBufferMaxSize,
>>>                                   (EFI_PHYSICAL_ADDRESS *) 
>>> &mNsBufferAddress,
>>>                                   ImageHandle,
>>>                                   NULL);
>>>
>>> The address of the buffer is 0xfbe00000 and size is 0x200000 i.e. it is 
>>> aligned
>>> to the page boundary. This call fails with EFI_NOT_FOUND. I am unable to 
>>> figure
>>> out what is going wrong. Am I using these interfaces in their intended way?
>>
>> I recall the following from the relevant volume of the PI spec (please
>> look it up and double check it): when you add memory space of type
>> EfiGcdMemoryTypeSystemMemory, it is immediately absorbed by the pool /
>> page UEFI memory allocation services, for their internal management. So
>> after you add this, you can't allocate memory *space* of
>> EfiGcdMemoryTypeSystemMemory. If you want to allocate system memory,
>> just use the AllocatePool() / AllocatePages() boot services.
> 
> Makes sense. The spec. says that the new memory range may be automatically
> allocated for use by UEFI memory services. The EDK2 implementation always does
> this in CoreAddMemorySpace() in MdeModulePkg/Core/Dxe/Gcd/Gcd.c.
> 
>>
>> The pattern that you use above is valid, but you should use a different
>> GCD memory type (probably EfiGcdMemoryTypeReserved).
> 
> I have not tried this memory type. I think there is a more basic problem. 
> Please
> see below!
> 
>>
>> If you definitely need "system memory" (= plain memory) to reside at
>> this address, and want to allocate it right after adding it to the
>> global coherency domain as EfiGcdMemoryTypeSystemMemory, then allocate
>> it with the AllocatePages() boot service, setting the first argument
>> (--> EFI_ALLOCATE_TYPE) to AllocateAddress (--> attempt to allocate at
>> the fixed address).
> 
> I gave this a try since a similar approach has been followed in some ARM
> platform code. However, it does not make a difference. I run into a Level 2
> translation fault as soon as I try to access the buffer. I have disabled cache
> state modelling so there are no TLBs or caches. So the translation fault is
> likely to be 'cause of an invalid/missing page table descriptor.  .
> 
> I think I am missing something obvious being a UEFI newbie. There are three
> steps that need to be undertaken in order to access this buffer.
> 
> 1. Add an identity mapped entry corresponding to the buffer in the translation
>    tables of the exception level UEFI is executing in (EL2 in my case).
> 
> 2. Add this buffer in the UEFI memory map so that it can either be consumed by
>    the memory allocation services or reserved.
> 
> 3. Allocate this buffer using its physical address so that it is not allocated
>    to another driver.
> 
> I was under the impression that gDS->AddMemorySpace() will perform both steps
> 1. and 2. However looking at the behaviour and the code, it seems that it does
> only 2.
> 
> Is it at all possible to do 1. after the translation tables have been created
> and the MMU initialised in the PEI phase. This essentially means adding 
> entries
> to live translation tables. Is this expected to be done through architecture
> specific mechanisms rather than the GCD services.

Is the base address of the new memory area above any other address that
you access otherwise?

I'm not sure about the aarch64 specifics here, but from my OvmfPkg
experience, I recall this: when you are about to enter the DXE phase,
the DXE IPL PEIM allocates memory from the permanent PEI RAM for page
tables, and builds the entire identity mapping that is supposed to be
relied on throughout DXE and BDS. How high this mapping extends is
governed by the CPU HOB that the HOB producer phase (~= PEI phase) produces.

In edk2 this HOB is generally produced with the BuildCpuHob() library
call (see "MdePkg/Include/Library/HobLib.h") in one of the platform PEIMs.

So, the CPU HOB should reflect the number of "value bits" of the
physical addresses that are expected to be accessed. For example, it has
to consider any 64-bit PCI MMIO aperture as well.

If your new area falls outside of the address space that is "announced"
by the CPU HOB, that would be consistent with the failure you're seeing,
in my opinion.

Thanks
Laszlo
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to