From: Michael Brown Date: Thu, 22 May 2025 10:58:11 +0000 (+0100) Subject: [uheap] Expose external heap region directly X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=11e01f0652daaf198317e2e13c8bb1d19f664ce9;p=thirdparty%2Fipxe.git [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 --- diff --git a/src/arch/x86/interface/pcbios/hidemem.c b/src/arch/x86/interface/pcbios/hidemem.c index 9a445d063..2b85459b6 100644 --- a/src/arch/x86/interface/pcbios/hidemem.c +++ b/src/arch/x86/interface/pcbios/hidemem.c @@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include #include /** Set to true if you want to test a fake E820 map */ @@ -132,18 +133,18 @@ void hide_textdata ( void ) { */ static void int15_sync ( void ) { physaddr_t start; - size_t size; + physaddr_t end; /* Besides our fixed base memory and textdata regions, we * support hiding only a single in-use memory region (the * umalloc region), which must be placed before the hidden * textdata region (even if zero-length). */ - start = uheap_used.start; - size = uheap_used.size; - if ( ! size ) - start = virt_to_phys ( _textdata ); - hide_region ( &hidemem_umalloc, start, ( start + size ) ); + start = uheap_start; + end = uheap_end; + if ( start == end ) + start = end = virt_to_phys ( _textdata ); + hide_region ( &hidemem_umalloc, start, end ); } /** diff --git a/src/core/uheap.c b/src/core/uheap.c index f5154a0d1..3f93bc030 100644 --- a/src/core/uheap.c +++ b/src/core/uheap.c @@ -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 */ diff --git a/src/image/initrd.c b/src/image/initrd.c index 71634324d..511f95f10 100644 --- a/src/image/initrd.c +++ b/src/image/initrd.c @@ -28,8 +28,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include -#include #include +#include #include /** @file @@ -41,9 +41,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** Maximum address available for initrd */ static physaddr_t initrd_top; -/** Minimum address available for initrd */ -static physaddr_t initrd_bottom; - /** * Squash initrds as high as possible in memory * @@ -236,9 +233,8 @@ void initrd_reshuffle ( physaddr_t bottom ) { size_t free_len; /* Calculate limits of available space for initrds */ - top = initrd_top; - if ( initrd_bottom > bottom ) - bottom = initrd_bottom; + top = ( initrd_top ? initrd_top : uheap_end ); + assert ( bottom >= uheap_limit ); /* Debug */ DBGC ( &images, "INITRD region [%#08lx,%#08lx)\n", bottom, top ); @@ -270,9 +266,8 @@ int initrd_reshuffle_check ( size_t len, physaddr_t bottom ) { size_t available; /* Calculate limits of available space for initrds */ - top = initrd_top; - if ( initrd_bottom > bottom ) - bottom = initrd_bottom; + top = ( initrd_top ? initrd_top : uheap_end ); + assert ( bottom >= uheap_limit ); available = ( top - bottom ); /* Allow for a sensible minimum amount of free space */ @@ -287,19 +282,19 @@ int initrd_reshuffle_check ( size_t len, physaddr_t bottom ) { * */ static void initrd_startup ( void ) { - size_t len; - /* Record largest memory block available. Do this after any - * allocations made during driver startup (e.g. large host - * memory blocks for Infiniband devices, which may still be in - * use at the time of rearranging if a SAN device is hooked) - * but before any allocations for downloaded images (which we - * can safely reuse when rearranging). + /* Record address above which reshuffling cannot take place. + * If any external heap allocations have been made during + * driver startup (e.g. large host memory blocks for + * Infiniband devices, which may still be in use at the time + * of rearranging if a SAN device is hooked), then we must not + * overwrite these allocations during reshuffling. */ - len = memmap_largest ( &initrd_bottom ); - initrd_top = ( initrd_bottom + len ); - DBGC ( &images, "INITRD largest memory block is [%#08lx,%#08lx)\n", - initrd_bottom, initrd_top ); + initrd_top = uheap_start; + if ( initrd_top ) { + DBGC ( &images, "INITRD limiting reshuffling to below " + "%#08lx\n", initrd_top ); + } } /** initrd startup function */ diff --git a/src/include/ipxe/memmap.h b/src/include/ipxe/memmap.h index 1283421bb..0175be11a 100644 --- a/src/include/ipxe/memmap.h +++ b/src/include/ipxe/memmap.h @@ -228,8 +228,6 @@ static inline void memmap_dump_all ( int hide ) { memmap_dump ( ®ion ); } -extern struct used_region uheap_used __used_region; - extern void memmap_update ( struct memmap_region *region, uint64_t start, uint64_t size, unsigned int flags, const char *name ); diff --git a/src/include/ipxe/uheap.h b/src/include/ipxe/uheap.h index 194c13175..d356786d3 100644 --- a/src/include/ipxe/uheap.h +++ b/src/include/ipxe/uheap.h @@ -15,4 +15,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define UMALLOC_PREFIX_uheap __uheap_ #endif +extern physaddr_t uheap_limit; +extern physaddr_t uheap_start; +extern physaddr_t uheap_end; + #endif /* _IPXE_UHEAP_H */