Skip to content

Commit

Permalink
SMF: Memory Distribution Logic Improvements
Browse files Browse the repository at this point in the history
An improvement to the memory distribution logic was suggested
in which the variable that keeps track of doubling the amount
of memory per pass could be removed. This commit removes the
variable and introduces a couple of other small changes.

Change-Id: I35cae2d6c2beac2ce91d94f439fd0dec1f782afc
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/68859
Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com>
Reviewed-by: Matthew Raybuck <mraybuc@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Michael Baiocchi <mbaiocch@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
  • Loading branch information
Ilya Smirnov authored and dcrowell77 committed Mar 1, 2019
1 parent ed35e3d commit 9ece0ed
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 29 deletions.
4 changes: 2 additions & 2 deletions src/include/usr/isteps/mem_utils.H
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ uint64_t get_top_mem_addr(const TARGETING::Target* i_proc);
/**
* @brief Utility function to obtain the lowest known address in the system
*
* @return the lowest know address in the system
* @return the lowest known address in the system
*/
uint64_t get_bottom_mem_addr();

Expand All @@ -62,7 +62,7 @@ uint64_t get_bottom_mem_addr();
* must not be nullptr or the func will assert
* must be of TYPE_PROC or the func will assert
*
* @return the lowest know address on the specified proc
* @return the lowest known address on the specified proc
*/
uint64_t get_bottom_mem_addr(const TARGETING::Target* i_proc);

Expand Down
40 changes: 40 additions & 0 deletions src/usr/secureboot/smf/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# SMF Memory Allocation Algorithm

### Introduction
The amount of Secure SMF memory to distribute between the available procs on the system
is a user-configurable petitboot setting. Hostboot reads this setting and distributes
the requested amount of memory as evenly as possible between the available procs on the
system.

**NOTE:** We must operate in power-of-two multiples of 256MB to satisfy hardware limitations. That means that the end result of the amount of secure memory behind each proc needs to be a power-of-two multiple of 256MB.

### The Algorithm
* The function to distribute the memory receives the requested amount (in bytes) as a uint64.
* A check is performed to see if the requested amount is 0 (do not allocate secure memory)
* SMF is turned off in that case
* A structure of proc and memory associations is built
* Each member of the struct consists of the proc target, the total available memory behind that proc, the amount of secure memory to be allocated behind that proc (0 initially), and the flag indicating whether the proc can still fit secure memory
* 8GB is subtracted from the available memory pool of the master proc to make sure hostboot has space to run in
* Start allocating the memory in chunks, starting with 256MB, and doubling the amount (where appropriate) every loop
* In a loop:
* Check if we've allocated all requested memory (or more)
* Check if the current chunk is more than we can fit under the proc
* **TRUE**: Flag the proc as out of memory (it will not be considered anymore)
* **FALSE**: "Pre-allocate" the current chunk behind the proc
* If we were able to allocate the current chunk, calculate the remaining amt to allocate
* If we've allocated everything or ran out of procs to allocate the memory on, break out of the loop
* Double the chunk to allocate for the next loop
* At the end of the loop two checks are performed:
* Check if we couldn't allocate any memory (the system is memory-starved) - return a predictive error
* Check if the actual allocated amount does not equal to the requested amount (there may have been rounding) - return an informational error

### Visual Representation of the Allocation Process

| Loop | Allocated on Proc 0 (MB) | Proc 1 | Proc 2|
| -----|:------------------------:| :------:|:-----:|
| 0 | 0 | 0 | 0 |
| 1 | 256 | 256 | 256 |
| 2 | 512 | 512 | 512 |
| 3 | 1024 | 1024 | 1024 |
| 4 | 2048 | 2048 | 2048 |
... repeat until allocated or until there are no more remaining procs with memory
40 changes: 13 additions & 27 deletions src/usr/secureboot/smf/smf.C
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ errlHndl_t distributeSmfMem(const uint64_t i_requestedSmfMemAmtInBytes,

int64_t l_remainingAmtToAllocate = i_requestedSmfMemAmtInBytes;
uint64_t l_currChunkSize = MIN_SMF_MEMORY_AMT;
bool l_doubleChunk = false;
uint64_t l_allocatedSoFar = 0;
uint64_t l_totalAllocated = 0;

Expand Down Expand Up @@ -161,47 +160,34 @@ errlHndl_t distributeSmfMem(const uint64_t i_requestedSmfMemAmtInBytes,
// The proc is out of memory; we can't use it any more
// in the allocation algorithm
l_member.useProc = false;
// We still need to allocate the current chunk to some other
// proc though, so don't increment the chunks for now.
l_doubleChunk = false;
TRACDCOMP(SMF_TRACE::g_trac_smf, "distributeSmfMem: proc 0x%x ran out of memory.", TARGETING::get_huid(l_member.proc));
}
else
{
// Can fit the current chunk.
l_member.memToAllocate = l_currChunkSize;

// We were able to allocate; now double the next chunk
l_doubleChunk = true;
}

// Tally up the total amt of memory allocated so far.
// We need to check this on each allocation (after each proc)
// because we may have to stop mid way through the proc loop
// when we've allocated all requested mem.
for(const auto& l_proc : i_procToMemVec)
{
l_allocatedSoFar += l_proc.memToAllocate;
}
// Tally up the total amt of memory allocated so far.
// We need to check this on each allocation after each proc
// because we may have to stop mid way through the proc loop
// when we've allocated all requested mem.
for(const auto& l_proc : i_procToMemVec)
{
l_allocatedSoFar += l_proc.memToAllocate;
}

if(l_doubleChunk)
{
// Only calculate the remaining amt when we've successfully
// allocated a chunk (which will force the boolean to
// be true). If we could not allocate the chunk, then the
// remaining amount didn't change.
// allocated a chunk. If we could not allocate the chunk,
// then the remaining amount didn't change.
l_remainingAmtToAllocate = i_requestedSmfMemAmtInBytes
- l_allocatedSoFar;
}
} // useProc
} // l_member

if(l_doubleChunk)
{
// Double the amt of mem we will try to allocate on the next
// iteration of the while loop.
l_currChunkSize = l_currChunkSize << 1;
}
// Double the amt of mem we will try to allocate on the next
// iteration of the while loop.
l_currChunkSize = l_currChunkSize << 1;

// Find out if we still have procs remaining. If not, then the
// user has requested too much memory to be allocated.
Expand Down

0 comments on commit 9ece0ed

Please sign in to comment.