From: Michael Brown Date: Mon, 19 May 2025 17:55:49 +0000 (+0100) Subject: [bios] Use generic external heap based on the system memory map X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d0c35b6823db973eb20f0bfdc3e4944f16952ad7;p=thirdparty%2Fipxe.git [bios] Use generic external heap based on the system memory map Signed-off-by: Michael Brown --- diff --git a/src/arch/x86/image/initrd.c b/src/arch/x86/image/initrd.c index 98c7a3804..3fc6964c9 100644 --- a/src/arch/x86/image/initrd.c +++ b/src/arch/x86/image/initrd.c @@ -29,7 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include -#include +#include #include /** @file @@ -287,7 +287,6 @@ int initrd_reshuffle_check ( size_t len, physaddr_t bottom ) { * */ static void initrd_startup ( void ) { - void *bottom; size_t len; /* Record largest memory block available. Do this after any @@ -297,9 +296,10 @@ static void initrd_startup ( void ) { * but before any allocations for downloaded images (which we * can safely reuse when rearranging). */ - len = largest_memblock ( &bottom ); - initrd_bottom = virt_to_phys ( bottom ); + 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 startup function */ diff --git a/src/arch/x86/include/bits/errfile.h b/src/arch/x86/include/bits/errfile.h index 0dadf4f01..6f9b45e7e 100644 --- a/src/arch/x86/include/bits/errfile.h +++ b/src/arch/x86/include/bits/errfile.h @@ -8,7 +8,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * @{ */ -#define ERRFILE_memtop_umalloc ( ERRFILE_ARCH | ERRFILE_CORE | 0x00000000 ) #define ERRFILE_int15 ( ERRFILE_ARCH | ERRFILE_CORE | 0x00010000 ) #define ERRFILE_pnpbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00020000 ) #define ERRFILE_bios_smbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00030000 ) diff --git a/src/arch/x86/include/bits/umalloc.h b/src/arch/x86/include/bits/umalloc.h deleted file mode 100644 index 5d1f554d8..000000000 --- a/src/arch/x86/include/bits/umalloc.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _BITS_UMALLOC_H -#define _BITS_UMALLOC_H - -/** @file - * - * x86-specific user memory allocation API implementations - * - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include - -#endif /* _BITS_UMALLOC_H */ diff --git a/src/arch/x86/include/ipxe/memtop_umalloc.h b/src/arch/x86/include/ipxe/memtop_umalloc.h deleted file mode 100644 index dee055d16..000000000 --- a/src/arch/x86/include/ipxe/memtop_umalloc.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _IPXE_MEMTOP_UMALLOC_H -#define _IPXE_MEMTOP_UMALLOC_H - -/** @file - * - * External memory allocation - * - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#ifdef UMALLOC_MEMTOP -#define UMALLOC_PREFIX_memtop -#else -#define UMALLOC_PREFIX_memtop __memtop_ -#endif - -#endif /* _IPXE_MEMTOP_UMALLOC_H */ diff --git a/src/arch/x86/interface/pcbios/hidemem.c b/src/arch/x86/interface/pcbios/hidemem.c index 4b80de076..9a445d063 100644 --- a/src/arch/x86/interface/pcbios/hidemem.c +++ b/src/arch/x86/interface/pcbios/hidemem.c @@ -139,8 +139,8 @@ static void int15_sync ( void ) { * umalloc region), which must be placed before the hidden * textdata region (even if zero-length). */ - start = umalloc_used.start; - size = umalloc_used.size; + start = uheap_used.start; + size = uheap_used.size; if ( ! size ) start = virt_to_phys ( _textdata ); hide_region ( &hidemem_umalloc, start, ( start + size ) ); diff --git a/src/arch/x86/interface/pcbios/memtop_umalloc.c b/src/arch/x86/interface/pcbios/memtop_umalloc.c deleted file mode 100644 index 3348263a5..000000000 --- a/src/arch/x86/interface/pcbios/memtop_umalloc.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (C) 2007 Michael Brown . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** - * @file - * - * External memory allocation - * - */ - -#include -#include -#include -#include -#include -#include -#include - -/** Maximum usable address for external allocated memory */ -#define EM_MAX_ADDRESS 0xffffffffUL - -/** Alignment of external allocated memory */ -#define EM_ALIGN ( 4 * 1024 ) - -/** An external memory block */ -struct external_memory { - /** Size of this memory block (excluding this header) */ - size_t size; - /** Block is currently in use */ - int used; -}; - -/** Top of heap */ -static void *top = NULL; - -/** Bottom of heap (current lowest allocated block) */ -static void *bottom = NULL; - -/** Remaining space on heap */ -static size_t heap_size; - -/** In-use memory region */ -struct used_region umalloc_used __used_region = { - .name = "umalloc", -}; - -/** - * Hide umalloc() region - * - * @v start Start of region - * @v end End of region - */ -static void hide_umalloc ( physaddr_t start, physaddr_t end ) { - - memmap_use ( &umalloc_used, start, ( end - start ) ); -} - -/** - * Find largest usable memory region - * - * @ret start Start of region - * @ret len Length of region - */ -size_t largest_memblock ( void **start ) { - struct memmap_region region; - physaddr_t max = EM_MAX_ADDRESS; - physaddr_t region_start; - physaddr_t region_end; - size_t region_len; - size_t len = 0; - - /* Avoid returning uninitialised data on error */ - *start = NULL; - - /* Scan through all memory regions */ - for_each_memmap ( ®ion, 1 ) { - - /* Truncate block to maximum physical address */ - memmap_dump ( ®ion ); - if ( region.addr > max ) { - DBGC ( ®ion, "...starts after maximum address " - "%lx\n", max ); - break; - } - region_start = region.addr; - if ( ! memmap_is_usable ( ®ion ) ) - continue; - region_end = ( region_start + memmap_size ( ®ion ) ); - if ( region_end > max ) { - DBGC ( ®ion, "...end truncated to maximum address " - "%lx\n", max); - region_end = 0; /* =max, given the wraparound */ - } - region_len = ( region_end - region_start ); - - /* Use largest block */ - if ( region_len > len ) { - DBG ( "...new best block found\n" ); - *start = phys_to_virt ( region_start ); - len = region_len; - } - } - - return len; -} - -/** - * Initialise external heap - * - */ -static void init_eheap ( void ) { - void *base; - - heap_size = largest_memblock ( &base ); - bottom = top = ( base + heap_size ); - DBG ( "External heap grows downwards from %lx (size %zx)\n", - virt_to_phys ( top ), heap_size ); -} - -/** - * Collect free blocks - * - */ -static void ecollect_free ( void ) { - struct external_memory extmem; - size_t len; - - /* Walk the free list and collect empty blocks */ - while ( bottom != top ) { - memcpy ( &extmem, ( bottom - sizeof ( extmem ) ), - sizeof ( extmem ) ); - if ( extmem.used ) - break; - DBG ( "EXTMEM freeing [%lx,%lx)\n", virt_to_phys ( bottom ), - ( virt_to_phys ( bottom ) + extmem.size ) ); - len = ( extmem.size + sizeof ( extmem ) ); - bottom += len; - heap_size += len; - } -} - -/** - * Reallocate external memory - * - * @v old_ptr Memory previously allocated by umalloc(), or NULL - * @v new_size Requested size - * @ret new_ptr Allocated memory, or NULL - * - * Calling realloc() with a new size of zero is a valid way to free a - * memory block. - */ -static void * memtop_urealloc ( void *ptr, size_t new_size ) { - struct external_memory extmem; - void *new = ptr; - size_t align; - - /* (Re)initialise external memory allocator if necessary */ - if ( bottom == top ) - init_eheap(); - - /* Get block properties into extmem */ - if ( ptr && ( ptr != NOWHERE ) ) { - /* Determine old size */ - memcpy ( &extmem, ( ptr - sizeof ( extmem ) ), - sizeof ( extmem ) ); - } else { - /* Create a zero-length block */ - if ( heap_size < sizeof ( extmem ) ) { - DBG ( "EXTMEM out of space\n" ); - return NULL; - } - ptr = bottom = ( bottom - sizeof ( extmem ) ); - heap_size -= sizeof ( extmem ); - DBG ( "EXTMEM allocating [%lx,%lx)\n", - virt_to_phys ( ptr ), virt_to_phys ( ptr ) ); - extmem.size = 0; - } - extmem.used = ( new_size > 0 ); - - /* Expand/shrink block if possible */ - if ( ptr == bottom ) { - /* Update block */ - new = ( ptr - ( new_size - extmem.size ) ); - align = ( virt_to_phys ( new ) & ( EM_ALIGN - 1 ) ); - new_size += align; - new -= align; - if ( new_size > ( heap_size + extmem.size ) ) { - DBG ( "EXTMEM out of space\n" ); - return NULL; - } - DBG ( "EXTMEM expanding [%lx,%lx) to [%lx,%lx)\n", - virt_to_phys ( ptr ), - ( virt_to_phys ( ptr ) + extmem.size ), - virt_to_phys ( new ), - ( virt_to_phys ( new ) + new_size ) ); - memmove ( new, ptr, ( ( extmem.size < new_size ) ? - extmem.size : new_size ) ); - bottom = new; - heap_size -= ( new_size - extmem.size ); - extmem.size = new_size; - } else { - /* Cannot expand; can only pretend to shrink */ - if ( new_size > extmem.size ) { - /* Refuse to expand */ - DBG ( "EXTMEM cannot expand [%lx,%lx)\n", - virt_to_phys ( ptr ), - ( virt_to_phys ( ptr ) + extmem.size ) ); - return NULL; - } - } - - /* Write back block properties */ - memcpy ( ( new - sizeof ( extmem ) ), &extmem, sizeof ( extmem ) ); - - /* Collect any free blocks and update hidden memory region */ - ecollect_free(); - hide_umalloc ( ( virt_to_phys ( bottom ) - - ( ( bottom == top ) ? 0 : sizeof ( extmem ) ) ), - virt_to_phys ( top ) ); - - return ( new_size ? new : NOWHERE ); -} - -PROVIDE_UMALLOC ( memtop, urealloc, memtop_urealloc ); diff --git a/src/config/defaults/pcbios.h b/src/config/defaults/pcbios.h index 0f25669e4..4ccc2b0da 100644 --- a/src/config/defaults/pcbios.h +++ b/src/config/defaults/pcbios.h @@ -16,7 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define TIMER_PCBIOS #define CONSOLE_PCBIOS #define NAP_PCBIOS -#define UMALLOC_MEMTOP +#define UMALLOC_UHEAP #define MEMMAP_INT15 #define SMBIOS_PCBIOS #define SANBOOT_PCBIOS diff --git a/src/include/ipxe/memblock.h b/src/include/ipxe/memblock.h deleted file mode 100644 index 4b6c64156..000000000 --- a/src/include/ipxe/memblock.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _IPXE_MEMBLOCK_H -#define _IPXE_MEMBLOCK_H - -/** @file - * - * Largest memory block - * - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include - -extern size_t largest_memblock ( void **start ); - -#endif /* _IPXE_MEMBLOCK_H */ diff --git a/src/include/ipxe/memmap.h b/src/include/ipxe/memmap.h index 1d0aaa372..1283421bb 100644 --- a/src/include/ipxe/memmap.h +++ b/src/include/ipxe/memmap.h @@ -228,7 +228,7 @@ static inline void memmap_dump_all ( int hide ) { memmap_dump ( ®ion ); } -extern struct used_region umalloc_used __used_region; +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,