Jordan,

UEFI Boot Service FreePages() is mapped to CoreFreePages().
CoreFreePages() calls CoreConvertPages() with NewType of EfiConventionalMemory.
CoreConvertPages() calls CoreAddRange() with NewType of EfiConventionalMemory.

Memory registration occurs in GCD init and additional memory can be registered 
dynamically through GCD service calls.  All of the GCD paths go through 
CoreAddMemoryDescriptor() and CoreAddMemoryDescriptor() calls CoreAddRange().

The patch is in CoreAddRange() that zeros page zero.  This is the function that 
is common to the registration of memory and free pages operations, so this work 
could be done in a single place.

I agree I should have broken this up into two patches since one is a new 
feature and the other is a bug.  I will break it up for checkin.

Given that the only consumer of DEBUG_CLEAR_MEMORY() is the UEFI Memory Manager 
in the DXE Core, I do not think adding more versions of it makes sense.  
Another implementation option is to move the checks for clearing of page zero 
into the implementation of the DEBUG_CLEAR_MEMORY() macro itself and update the 
definition of DEBUG_CLEAR_MEMORY() to state that address range 0x0-0xfff is 
ignored.

/**  
  The macro that calls DebugClearMemory() to clear a buffer to a default value.

  If the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set, 
  then this macro calls DebugClearMemory() passing in Address and Length.

  @param  Address  The pointer to a buffer.
  @param  Length   The number of bytes in the buffer to set.

**/
#define DEBUG_CLEAR_MEMORY(Address, Length)  \
  do {                                       \
    if (DebugClearMemoryEnabled ()) {        \
      DebugClearMemory (Address, Length);    \
    }                                        \
  } while (FALSE)

Thanks,

Mike

-----Original Message-----
From: Jordan Justen [mailto:jljus...@gmail.com] 
Sent: Thursday, March 21, 2013 8:23 AM
To: edk2-devel@lists.sourceforge.net
Subject: Re: [edk2] MdeModulePkg patch: DxeCore UEFI Memory Manager zero page 
zero and page zero DEBUG_CLEAR_MEMORY() bug fix

On Thu, Mar 21, 2013 at 4:25 AM, Laszlo Ersek <ler...@redhat.com> wrote:
> On 03/21/13 00:38, Kinney, Michael D wrote:
>> Please see the attached patch that guarantees that free memory in the 4K
>> page starting at address 0 is always cleared to 0.  The algorithm is to
>> clear page zero if it is registered with the DXE Core with type
>> EfiConventionalMemory,

>> and to also clear page zero if it is freed using
>> the UEFI Boot Service FreePages().

Where does this happen?

>The unit test for this patch exposed
>> a bug in the DXE Core that generated an ASSERT() when the page at
>> address zero is freed and DEBUG_CLEAR_MEMORY() macros are enabled.  If
>> DEBUG_CLEAR_MEMORY() is enabled and the page at address 0 is freed, then
>> DEBUG_CLEAR_MEMORY() is invoked skipping over the first 4K page.

This seems to be a bug fix, and I think should be made separately.

>> This patch improves OS compatibility for OSes that may evaluate page 0
>> for legacy data structures.  Before this patch, free memory may contain
>> random values which induces random boot failures for some OSes.  This
>> patch may also help find NULL pointer bugs sooner because all of the
>> fields in a data structure dereferenced through NULL will also be NULL now.
>
> I'm including the patch here for review:

Thanks for including the patch inline Laszlo. (A nice feature of git
send-email...)

>> Index: Dxe/Mem/Page.c
>> ===================================================================
>> --- Dxe/Mem/Page.c    (revision 14133)
>> +++ Dxe/Mem/Page.c    (working copy)
>> @@ -1,7 +1,7 @@
>>  /** @file
>>    UEFI Memory page management functions.
>>
>> -Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
>> +Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
>>  This program and the accompanying materials
>>  are licensed and made available under the terms and conditions of the BSD 
>> License
>>  which accompanies this distribution.  The full text of the license may be 
>> found at
>> @@ -177,8 +177,21 @@
>>    ASSERT_LOCKED (&gMemoryLock);
>>
>>    DEBUG ((DEBUG_PAGE, "AddRange: %lx-%lx to %d\n", Start, End, Type));
>> -
>> +
>>    //
>> +  // If memory of type EfiConventionalMemory is being added that includes 
>> the page
>> +  // starting at address 0, then zero the page starting at address 0.  This 
>> has
>> +  // two benifits.  It helps find NULL pointer bugs and it also maximizes
>> +  // compatibility with operating systems that may evaluate memory in this 
>> page
>> +  // for legacy data structures.  If memory of any other type is added 
>> starting
>> +  // at address 0, then do not zero the page at address 0 because the page 
>> is being
>> +  // used for other purposes.
>> +  //
>> +  if (Type == EfiConventionalMemory && Start == 0 && (End >= EFI_PAGE_SIZE 
>> - 1)) {
>> +    SetMem ((VOID *)(UINTN)Start, EFI_PAGE_SIZE, 0);
>> +  }
>> +
>> +  //
>>    // Memory map being altered so updated key
>>    //
>>    mMemoryMapKey += 1;
>
> This hunk (for function CoreAddRange()) seems OK. "End" is inclusive,
> hence we're checking whether the range being added covers the zero page
> entirely.

This should be a separate patch from the change below. For this part:
Reviewed-by: Jordan Justen <jordan.l.jus...@intel.com>

>> @@ -834,7 +847,18 @@
>>      //
>>      CoreAddRange (NewType, Start, RangeEnd, Attribute);
>>      if (NewType == EfiConventionalMemory) {
>> -      DEBUG_CLEAR_MEMORY ((VOID *)(UINTN) Start, (UINTN) (RangeEnd - Start 
>> + 1));
>> +      //
>> +      // Avoid calling DEBUG_CLEAR_MEMORY() for an address of 0 because this
>> +      // macro will ASSERT() if address is 0.  Instead, CoreAddRange() 
>> guarantees
>> +      // that the page starting at address 0 is always filled with zeros.
>> +      //
>> +      if (Start == 0) {
>> +        if (RangeEnd > EFI_PAGE_SIZE) {
>> +          DEBUG_CLEAR_MEMORY ((VOID *)(UINTN) EFI_PAGE_SIZE, (UINTN) 
>> (RangeEnd - EFI_PAGE_SIZE + 1));
>> +        }
>> +      } else {
>> +        DEBUG_CLEAR_MEMORY ((VOID *)(UINTN) Start, (UINTN) (RangeEnd - 
>> Start + 1));
>> +      }
>>      }

Maybe another option is to add
DEBUG_CLEAR_MEMORY_AT_0(Length)/DebugClearMemoryAt0
or
DEBUG_CLEAR_MEMORY_UNCHECKED?

-Jordan

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to