On 03/05/2018 12:22 PM, Laszlo Ersek wrote:
PEIMs generally "execute in place" (XIP), i.e. they run from flash, not
RAM. In this status they use "temporary RAM" (e.g. CPU caches configured
like RAM) for stack & heap; whatever HOBs they produce are stored in
"temp RAM" as well. Then one of the PEIMs "discovers permanent RAM"
(basically it programs the memory controller and publishes the RAM
ranges). In turn the PEI core "migrates" PEIMs from temporary to
permanent RAM, including the HOB list.

Before the temporary RAM migration (when still executing in place from
flash), PEIMs cannot have writeable global variables. For example,
dynamic PCDs are also maintained in a HOB (the PCD HOB).

A PEIM normally cannot (and shouldn't) tell whether it is dispatched
before or after permanent RAM is published. If needed, a PEIM can
advertise that it depends on permanent RAM (for example because it needs
a lot of heap memory) by including "gEfiPeiMemoryDiscoveredPpiGuid" in
its DEPEX.

Finally, it seems like a PEIM can also express, "I'm fine with being
dispatched from both flash (XIP) vs. permanent RAM, just the PEI core
tell me whichever it is". Apparently, if the PEIM is dispatched from
flash (before permanent RAM is available), its call to
RegisterForShadow() returns EFI_SUCCESS (and then its entry point
function will be invoked for a 2nd time, after the temp RAM migration).
And when a PEIM is dispatched from RAM (either for the very first time,
or for the second time, after being dispatched from flash first), the
same call returns EFI_ALREADY_STARTED.

Honestly, I'm unsure what this is good for (both in general, and
specifically for Tcg2Pei). Apparently, Tcg2Pei needs permanent RAM for
doing the measurements (which makes sense); I just wonder what exactly
it does so that it cannot simply specify
"gEfiPeiMemoryDiscoveredPpiGuid" in its DEPEX.

I haven't looked at this particular PEIM. But one case where registering for shadowing is useful is for improving performance when running from permanent RAM, where writable global variables are available. For instance, when running from flash, a ReportStatusCode PEIM may need to go through a slow process to locate an output hardware device on every PPI call. This may involve traversing the HOB list, consulting other PPIs, even probing hardware addresses. But once it's shadowed to RAM, it can locate the device once, then cache its address in a global. Not to mention that the code itself is far, far faster when run from RAM vs. flash. (That's probably a key difference between a real machine and a VM.)

Also, I've personally written a PEIM which saves a bunch of internal state in a HOB, since that's the main writable storage when running from flash. That state includes pointers to other data (in flash.) Once the data is all shadowed to RAM, it updates the HOB to point to the data in RAM. That way it's a lot faster to access the data.

I also have other PEIMs which are constrained (via DEPEX) to run *only* from RAM, since they have larger memory requirements than can be satisfied from temporary cache-as-RAM. That's certainly a valid technique as well.

RegisterForShadow() is a useful tool for making the most of the restricted PEI environment. And having it standardized like this is, as Andrew said, a lot better than the hacks people had to use beforehand.

Thanks,
--
Brian J. Johnson
Enterprise X86 Lab

Hewlett Packard Enterprise

brian.john...@hpe.com


Reply via email to