cancel
Showing results for 
Search instead for 
Did you mean: 

Archives Discussions

bkc177
Journeyman III

Disabling the DRAM Auto-Refresh During Boot

Dear AMD Developer Community,

I am using Coreboot to boot an AMD A6-5400K processor on an ASUS F2A85-M motherboard. During boot I would like to disable the auto-refresh of the DDR3 DRAM to measure its retention time (i.e. the length of time it can persist data in DRAM without refresh). The BDKG manual for my processor says there is a bit field DisAutoRefresh which can be used to disable the automatic refresh of DRAM. The AMD AGESA vendor code in Coreboot provides an interface for reading/writing this bit (see here for an example).

I am using this interface to disable the automatic refresh after the memory initialization tasks and before deallocating the Northbridge register tables (here). My code at that location looks something like this.

#define REFRESH_DELAY_MSECS 64

UINTN CurAddr, StartAddr = 0x1000000, EndAddr = 0x8000000;

UINT32 Errors, Secs = RETENTION_TIME_STEP_SIZE_SECS;

while (Secs <= RETENTION_TIME_MAX_SECS) {

     // 1. Write `Pattern` to addresses in given range.

     for (CurAddr = StartAddr; CurAddr < EndAddr; CurAddr += sizeof(UINTN)) {

          MemWritePhys(CurAddr, Pattern);

     }

     // 2. Wait for writes to complete.

     MemPhysMemBarrier();

     // 3. Flush cache in case it is caching values.

     for (CurAddr = StartAddr; CurAddr < EndAddr; CurAddr += sizeof(UINTN)) {

          MemClFlush(CurAddr);

     }

     // 4. Wait for writes to complete.

     MemPhysMemBarrier();

     // 5. Refresh all cells before disabling Auto-Refresh.

     mdelay(REFRESH_DELAY_MSECS);

     // 6. Disable DRAM Auto-Refresh.

     MemNSetBitFieldNb(NBPtr, BFDisAutoRefresh, 1);

     // 7. Wait `Secs` seconds (i.e. the retention time).

     delay(Secs);

     // 8. Re-Enable DRAM Auto-Refresh.

     MemNSetBitFieldNb(NBPtr, BFDisAutoRefresh, 0);

     // 9. Refresh all cells before reading their values.

     mdelay(REFRESH_DELAY_MSECS);

     // 10. Count the number of values that did not persist across the delay.

     Errors = 0;

     for (CurAddr = StartAddr; CurAddr < EndAddr; CurAddr += sizeof(UINTN)) {

          if (MemReadPhys(CurAddr) != Pattern) {

               Errors++;

          }

     }

     // 11. Report results.

     printk(BIOS_DEBUG, "\tRetentionTime = %d seconds --> %d errors.\n", Secs, Errors);

     // 12. Increase the retention time and repeat.

     Secs += RETENTION_TIME_STEP_SIZE_SECS;

}

where MemWritePhys writes to DRAM  without caching the value (using movnti instruction), MemReadPhys reads the value at the given address, MemPhysMemBarrier is implemented as a memory fence, and MemClFlush is implemented as a wrapper around MemUFlushPattern (defined here).

I am finding that even after long periods of delay (more than 30 minutes), there is no degradation of the values stored in DRAM despite the automatic refresh being disabled. My question is whether there are any other parameters/switches I need to set in order to put the DRAM into such a state. For instance, does the DRAM automatically enter self-refresh when automatic refresh is disabled? (The BDKG does not seem to imply this functionality, but that could be one explanation). In addition, it is possible that this is not the right place to be inserting this code and another location may be more effective for getting the results I'm looking for.

Thank you for your help!

Berj

0 Likes
0 Replies