[uheap] Expose external heap region directly

We currently rely on implicit detection of the external heap region.
The INT 15 memory map mangler relies on examining the corresponding
in-use memory region, and the initrd reshuffler relies on performing a
separate detection of the largest free memory block after startup has
completed.

Replace these with explicit public symbols to describe the external
heap region.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-05-22 11:58:11 +01:00
parent e056041074
commit 11e01f0652
5 changed files with 55 additions and 51 deletions
+28 -22
View File
@@ -50,31 +50,38 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
static struct heap uheap;
/** Minimum possible start of external heap */
physaddr_t uheap_limit;
/** Start of external heap */
physaddr_t uheap_start;
/** End of external heap */
physaddr_t uheap_end;
/** In-use memory region */
struct used_region uheap_used __used_region = {
.name = "uheap",
};
/** External heap maximum size */
static size_t uheap_max;
/**
* Adjust size of external heap in-use memory region
*
* @v delta Size change
*/
static void uheap_resize ( ssize_t delta ) {
physaddr_t top;
/* Update in-use memory region */
assert ( ( uheap_used.start & ( UHEAP_ALIGN - 1 ) ) == 0 );
assert ( ( uheap_used.size & ( UHEAP_ALIGN - 1 ) ) == 0 );
assert ( ( delta & ( UHEAP_ALIGN - 1 ) ) == 0 );
memmap_use ( &uheap_used, ( uheap_used.start - delta ),
( uheap_used.size + delta ) );
top = ( uheap_used.start + uheap_used.size );
DBGC ( &uheap, "UHEAP now at [%#08lx,%#08lx)\n",
uheap_used.start, top );
uheap_start -= delta;
assert ( uheap_limit <= uheap_start );
assert ( uheap_start <= uheap_end );
assert ( ( uheap_limit & ( UHEAP_ALIGN - 1 ) ) == 0 );
assert ( ( uheap_start & ( UHEAP_ALIGN - 1 ) ) == 0 );
assert ( ( uheap_end & ( UHEAP_ALIGN - 1 ) ) == 0 );
memmap_use ( &uheap_used, uheap_start, ( uheap_end - uheap_start ) );
DBGC ( &uheap, "UHEAP now at (%#08lx)...[%#08lx,%#08lx)\n",
uheap_limit, uheap_start, uheap_end );
memmap_dump_all ( 1 );
}
@@ -91,8 +98,9 @@ static void uheap_find ( void ) {
size_t size;
/* Sanity checks */
assert ( uheap_start == uheap_end );
assert ( uheap_limit == uheap_end );
assert ( uheap_used.size == 0 );
assert ( uheap_max == 0 );
/* Find the largest region within the system memory map */
size = memmap_largest ( &start );
@@ -112,12 +120,10 @@ static void uheap_find ( void ) {
assert ( ( end - start ) == size );
/* Record region */
assert ( ( start & ( UHEAP_ALIGN - 1 ) ) == 0 );
assert ( ( size & ( UHEAP_ALIGN - 1 ) ) == 0 );
assert ( ( end & ( UHEAP_ALIGN - 1 ) ) == 0 );
uheap_max = size;
uheap_used.start = end;
DBGC ( &uheap, "UHEAP grows downwards from %#08lx\n", end );
uheap_limit = start;
uheap_start = end;
uheap_end = end;
uheap_resize ( 0 );
}
/**
@@ -130,15 +136,15 @@ static unsigned int uheap_grow ( size_t size ) {
void *new;
/* Initialise heap, if it does not yet exist */
if ( ! uheap_max )
if ( uheap_limit == uheap_end )
uheap_find();
/* Fail if insufficient space remains */
if ( size > ( uheap_max - uheap_used.size ) )
if ( size > ( uheap_start - uheap_limit ) )
return 0;
/* Grow heap */
new = ( phys_to_virt ( uheap_used.start ) - size );
new = ( phys_to_virt ( uheap_start ) - size );
heap_populate ( &uheap, new, size );
uheap_resize ( size );
@@ -155,7 +161,7 @@ static unsigned int uheap_grow ( size_t size ) {
static unsigned int uheap_shrink ( void *ptr, size_t size ) {
/* Do nothing unless this is the lowest block in the heap */
if ( virt_to_phys ( ptr ) != uheap_used.start )
if ( virt_to_phys ( ptr ) != uheap_start )
return 0;
/* Shrink heap */