]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[bios] Use generic external heap based on the system memory map
authorMichael Brown <mcb30@ipxe.org>
Mon, 19 May 2025 17:55:49 +0000 (18:55 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 19 May 2025 19:47:21 +0000 (20:47 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/x86/image/initrd.c
src/arch/x86/include/bits/errfile.h
src/arch/x86/include/bits/umalloc.h [deleted file]
src/arch/x86/include/ipxe/memtop_umalloc.h [deleted file]
src/arch/x86/interface/pcbios/hidemem.c
src/arch/x86/interface/pcbios/memtop_umalloc.c [deleted file]
src/config/defaults/pcbios.h
src/include/ipxe/memblock.h [deleted file]
src/include/ipxe/memmap.h

index 98c7a3804f0751a9c2aa45a81869d8a3daa78726..3fc6964c96cf57fd2a9dada19b405df9a51eb141 100644 (file)
@@ -29,7 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <ipxe/image.h>
 #include <ipxe/uaccess.h>
 #include <ipxe/init.h>
-#include <ipxe/memblock.h>
+#include <ipxe/memmap.h>
 #include <ipxe/cpio.h>
 
 /** @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 */
index 0dadf4f01c2861c28ed9f3ffebf111c02c79d232..6f9b45e7e25480e71ccd10e833695e459d4028fd 100644 (file)
@@ -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 (file)
index 5d1f554..0000000
+++ /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 <ipxe/memtop_umalloc.h>
-
-#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 (file)
index dee055d..0000000
+++ /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 */
index 4b80de076a0c66399ccbc05c90fbab10fec7e5f7..9a445d0632106dd51576d46525e9a79ee54100e7 100644 (file)
@@ -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 (file)
index 3348263..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * 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 <limits.h>
-#include <string.h>
-#include <errno.h>
-#include <ipxe/uaccess.h>
-#include <ipxe/memblock.h>
-#include <ipxe/memmap.h>
-#include <ipxe/umalloc.h>
-
-/** 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 ( &region, 1 ) {
-
-               /* Truncate block to maximum physical address */
-               memmap_dump ( &region );
-               if ( region.addr > max ) {
-                       DBGC ( &region, "...starts after maximum address "
-                              "%lx\n", max );
-                       break;
-               }
-               region_start = region.addr;
-               if ( ! memmap_is_usable ( &region ) )
-                       continue;
-               region_end = ( region_start + memmap_size ( &region ) );
-               if ( region_end > max ) {
-                       DBGC ( &region, "...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 );
index 0f25669e49c815c01679c15367e4dfcea65b9b8c..4ccc2b0da404c85383433ca0d86d8aa601607a7d 100644 (file)
@@ -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 (file)
index 4b6c641..0000000
+++ /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 <stdint.h>
-
-extern size_t largest_memblock ( void **start );
-
-#endif /* _IPXE_MEMBLOCK_H */
index 1d0aaa3721bc1cacdcccf1180c2764c636338fbf..1283421bb34a8d9b4452c62cd8ada760e6e321a6 100644 (file)
@@ -228,7 +228,7 @@ static inline void memmap_dump_all ( int hide ) {
                memmap_dump ( &region );
 }
 
-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,