*
*/
-/** Equivalent of NOWHERE for user pointers */
-#define UNOWHERE ( ~UNULL )
-
/**
* Reallocate external memory
*
- * @v old_ptr Memory previously allocated by umalloc(), or UNULL
+ * @v old_ptr Memory previously allocated by umalloc(), or NULL
* @v new_size Requested size
- * @ret new_ptr Allocated memory, or UNULL
+ * @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 userptr_t sbi_urealloc ( userptr_t old_ptr, size_t new_size ) {
+static void * sbi_urealloc ( void * old_ptr, size_t new_size ) {
/* External allocation not yet implemented: allocate from heap */
- return ( ( userptr_t ) realloc ( ( ( void * ) old_ptr ), new_size ) );
+ return ( realloc ( old_ptr, new_size ) );
}
PROVIDE_UMALLOC ( sbi, urealloc, sbi_urealloc );
/** Alignment of external allocated memory */
#define EM_ALIGN ( 4 * 1024 )
-/** Equivalent of NOWHERE for user pointers */
-#define UNOWHERE ( ( userptr_t ) ~( ( intptr_t ) 0 ) )
-
/** An external memory block */
struct external_memory {
/** Size of this memory block (excluding this header) */
};
/** Top of heap */
-static userptr_t top = UNULL;
+static void *top = NULL;
/** Bottom of heap (current lowest allocated block) */
-static userptr_t bottom = UNULL;
+static void *bottom = NULL;
/** Remaining space on heap */
static size_t heap_size;
* @ret start Start of region
* @ret len Length of region
*/
-size_t largest_memblock ( userptr_t *start ) {
+size_t largest_memblock ( void **start ) {
struct memory_map memmap;
struct memory_region *region;
physaddr_t max = EM_MAX_ADDRESS;
size_t len = 0;
/* Avoid returning uninitialised data on error */
- *start = UNULL;
+ *start = NULL;
/* Scan through all memory regions */
get_memmap ( &memmap );
*
*/
static void init_eheap ( void ) {
- userptr_t base;
+ void *base;
heap_size = largest_memblock ( &base );
bottom = top = ( base + heap_size );
/* Walk the free list and collect empty blocks */
while ( bottom != top ) {
- copy_from_user ( &extmem, bottom, -sizeof ( extmem ),
- sizeof ( extmem ) );
+ memcpy ( &extmem, ( bottom - sizeof ( extmem ) ),
+ sizeof ( extmem ) );
if ( extmem.used )
break;
DBG ( "EXTMEM freeing [%lx,%lx)\n", virt_to_phys ( bottom ),
/**
* Reallocate external memory
*
- * @v old_ptr Memory previously allocated by umalloc(), or UNULL
+ * @v old_ptr Memory previously allocated by umalloc(), or NULL
* @v new_size Requested size
- * @ret new_ptr Allocated memory, or UNULL
+ * @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 userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
+static void * memtop_urealloc ( void *ptr, size_t new_size ) {
struct external_memory extmem;
- userptr_t new = ptr;
+ void *new = ptr;
size_t align;
/* (Re)initialise external memory allocator if necessary */
init_eheap();
/* Get block properties into extmem */
- if ( ptr && ( ptr != UNOWHERE ) ) {
+ if ( ptr && ( ptr != NOWHERE ) ) {
/* Determine old size */
- copy_from_user ( &extmem, ptr, -sizeof ( extmem ),
- sizeof ( extmem ) );
+ 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 UNULL;
+ return NULL;
}
ptr = bottom = ( bottom - sizeof ( extmem ) );
heap_size -= sizeof ( extmem );
new -= align;
if ( new_size > ( heap_size + extmem.size ) ) {
DBG ( "EXTMEM out of space\n" );
- return UNULL;
+ return NULL;
}
DBG ( "EXTMEM expanding [%lx,%lx) to [%lx,%lx)\n",
virt_to_phys ( ptr ),
DBG ( "EXTMEM cannot expand [%lx,%lx)\n",
virt_to_phys ( ptr ),
( virt_to_phys ( ptr ) + extmem.size ) );
- return UNULL;
+ return NULL;
}
}
/* Write back block properties */
- copy_to_user ( new, -sizeof ( extmem ), &extmem,
- sizeof ( extmem ) );
+ memcpy ( ( new - sizeof ( extmem ) ), &extmem, sizeof ( extmem ) );
/* Collect any free blocks and update hidden memory region */
ecollect_free();
( ( bottom == top ) ? 0 : sizeof ( extmem ) ) ),
virt_to_phys ( top ) );
- return ( new_size ? new : UNOWHERE );
+ return ( new_size ? new : NOWHERE );
}
PROVIDE_UMALLOC ( memtop, urealloc, memtop_urealloc );
* @v align Physical alignment
* @ret addr Buffer address, or NULL on error
*/
-static userptr_t dma_op_umalloc ( struct dma_device *dma,
- struct dma_mapping *map,
- size_t len, size_t align ) {
+static void * dma_op_umalloc ( struct dma_device *dma,
+ struct dma_mapping *map,
+ size_t len, size_t align ) {
struct dma_operations *op = dma->op;
if ( ! op )
* @v addr Buffer address
* @v len Length of buffer
*/
-static void dma_op_ufree ( struct dma_mapping *map, userptr_t addr,
- size_t len ) {
+static void dma_op_ufree ( struct dma_mapping *map, void *addr, size_t len ) {
struct dma_device *dma = map->dma;
assert ( dma != NULL );
char data[0];
};
-/**
- * Address for zero-length memory blocks
- *
- * @c malloc(0) or @c realloc(ptr,0) will return the special value @c
- * NOWHERE. Calling @c free(NOWHERE) will have no effect.
- *
- * This is consistent with the ANSI C standards, which state that
- * "either NULL or a pointer suitable to be passed to free()" must be
- * returned in these cases. Using a special non-NULL value means that
- * the caller can take a NULL return value to indicate failure,
- * without first having to check for a requested size of zero.
- *
- * Code outside of malloc.c do not ever need to refer to the actual
- * value of @c NOWHERE; this is an internal definition.
- */
-#define NOWHERE ( ( void * ) ~( ( intptr_t ) 0 ) )
-
/** List of free memory blocks */
static LIST_HEAD ( free_blocks );
* @ret rc Return status code
*/
static int xferbuf_umalloc_realloc ( struct xfer_buffer *xferbuf, size_t len ) {
- userptr_t *udata = xferbuf->data;
- userptr_t new_udata;
+ void **udata = xferbuf->data;
+ void *new_udata;
new_udata = urealloc ( *udata, len );
if ( ! new_udata )
*/
static void xferbuf_umalloc_write ( struct xfer_buffer *xferbuf, size_t offset,
const void *data, size_t len ) {
- userptr_t *udata = xferbuf->data;
+ void **udata = xferbuf->data;
- copy_to_user ( *udata, offset, data, len );
+ memcpy ( ( *udata + offset ), data, len );
}
/**
*/
static void xferbuf_umalloc_read ( struct xfer_buffer *xferbuf, size_t offset,
void *data, size_t len ) {
- userptr_t *udata = xferbuf->data;
+ void **udata = xferbuf->data;
- copy_from_user ( data, *udata, offset, len );
+ memcpy ( data, ( *udata + offset ), len );
}
/** umalloc()-based data buffer operations */
* @v align Physical alignment
* @ret addr Buffer address, or NULL on error
*/
- userptr_t ( * umalloc ) ( struct dma_device *dma,
- struct dma_mapping *map,
- size_t len, size_t align );
+ void * ( * umalloc ) ( struct dma_device *dma,
+ struct dma_mapping *map,
+ size_t len, size_t align );
/**
* Unmap and free DMA-coherent buffer from external (user) memory
*
* @v len Length of buffer
*/
void ( * ufree ) ( struct dma_device *dma, struct dma_mapping *map,
- userptr_t addr, size_t len );
+ void *addr, size_t len );
/**
* Set addressable space mask
*
* @v align Physical alignment
* @ret addr Buffer address, or NULL on error
*/
-static inline __always_inline userptr_t
+static inline __always_inline void *
DMAAPI_INLINE ( flat, dma_umalloc ) ( struct dma_device *dma,
struct dma_mapping *map,
size_t len, size_t align __unused ) {
- userptr_t addr;
+ void *addr;
/* Allocate buffer */
addr = umalloc ( len );
*/
static inline __always_inline void
DMAAPI_INLINE ( flat, dma_ufree ) ( struct dma_mapping *map,
- userptr_t addr, size_t len __unused ) {
+ void *addr, size_t len __unused ) {
/* Free buffer */
ufree ( addr );
* @v align Physical alignment
* @ret addr Buffer address, or NULL on error
*/
-userptr_t dma_umalloc ( struct dma_device *dma, struct dma_mapping *map,
- size_t len, size_t align );
+void * dma_umalloc ( struct dma_device *dma, struct dma_mapping *map,
+ size_t len, size_t align );
/**
* Unmap and free DMA-coherent buffer from external (user) memory
* @v addr Buffer address
* @v len Length of buffer
*/
-void dma_ufree ( struct dma_mapping *map, userptr_t addr, size_t len );
+void dma_ufree ( struct dma_mapping *map, void *addr, size_t len );
/**
* Set addressable space mask
#include <ipxe/tables.h>
#include <valgrind/memcheck.h>
+/**
+ * Address for zero-length memory blocks
+ *
+ * @c malloc(0) or @c realloc(ptr,0) will return the special value @c
+ * NOWHERE. Calling @c free(NOWHERE) will have no effect.
+ *
+ * This is consistent with the ANSI C standards, which state that
+ * "either NULL or a pointer suitable to be passed to free()" must be
+ * returned in these cases. Using a special non-NULL value means that
+ * the caller can take a NULL return value to indicate failure,
+ * without first having to check for a requested size of zero.
+ *
+ * Code outside of the memory allocators themselves does not ever need
+ * to refer to the actual value of @c NOWHERE; this is an internal
+ * definition.
+ */
+#define NOWHERE ( ( void * ) ~( ( intptr_t ) 0 ) )
+
extern size_t freemem;
extern size_t usedmem;
extern size_t maxusedmem;
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+#include <stddef.h>
#include <ipxe/api.h>
+#include <ipxe/malloc.h>
#include <config/umalloc.h>
-#include <ipxe/uaccess.h>
/**
* Provide a user memory allocation API implementation
/**
* Reallocate external memory
*
- * @v userptr Memory previously allocated by umalloc(), or UNULL
+ * @v old_ptr Memory previously allocated by umalloc(), or NULL
* @v new_size Requested size
- * @ret userptr Allocated memory, or UNULL
+ * @ret new_ptr Allocated memory, or NULL
*
* Calling realloc() with a new size of zero is a valid way to free a
* memory block.
*/
-userptr_t urealloc ( userptr_t userptr, size_t new_size );
+void * urealloc ( void *ptr, size_t new_size );
/**
* Allocate external memory
*
* @v size Requested size
- * @ret userptr Memory, or UNULL
+ * @ret ptr Memory, or NULL
*
* Memory is guaranteed to be aligned to a page boundary.
*/
-static inline __always_inline userptr_t umalloc ( size_t size ) {
- return urealloc ( UNULL, size );
+static inline __always_inline void * umalloc ( size_t size ) {
+ return urealloc ( NULL, size );
}
/**
* Free external memory
*
- * @v userptr Memory allocated by umalloc(), or UNULL
+ * @v ptr Memory allocated by umalloc(), or NULL
*
- * If @c ptr is UNULL, no action is taken.
+ * If @c ptr is NULL, no action is taken.
*/
-static inline __always_inline void ufree ( userptr_t userptr ) {
- urealloc ( userptr, 0 );
+static inline __always_inline void ufree ( void *ptr ) {
+ urealloc ( ptr, 0 );
}
#endif /* _IPXE_UMALLOC_H */
#include <stdint.h>
#include <ipxe/iobuf.h>
-#include <ipxe/uaccess.h>
#include <ipxe/interface.h>
#include <ipxe/xfer.h>
* @v data User pointer
*/
static inline __attribute__ (( always_inline )) void
-xferbuf_umalloc_init ( struct xfer_buffer *xferbuf, userptr_t *data ) {
+xferbuf_umalloc_init ( struct xfer_buffer *xferbuf, void **data ) {
xferbuf->data = data;
xferbuf->op = &xferbuf_umalloc_operations;
}
dma->allocated--;
}
-/**
- * Allocate and map DMA-coherent buffer from external (user) memory
- *
- * @v dma DMA device
- * @v map DMA mapping to fill in
- * @v len Length of buffer
- * @v align Physical alignment
- * @ret addr Buffer address, or NULL on error
- */
-static userptr_t efipci_dma_umalloc ( struct dma_device *dma,
- struct dma_mapping *map,
- size_t len, size_t align ) {
- void *addr;
-
- addr = efipci_dma_alloc ( dma, map, len, align );
- return virt_to_user ( addr );
-}
-
-/**
- * Unmap and free DMA-coherent buffer from external (user) memory
- *
- * @v dma DMA device
- * @v map DMA mapping
- * @v addr Buffer address
- * @v len Length of buffer
- */
-static void efipci_dma_ufree ( struct dma_device *dma, struct dma_mapping *map,
- userptr_t addr, size_t len ) {
-
- efipci_dma_free ( dma, map, addr, len );
-}
-
/**
* Set addressable space mask
*
.unmap = efipci_dma_unmap,
.alloc = efipci_dma_alloc,
.free = efipci_dma_free,
- .umalloc = efipci_dma_umalloc,
- .ufree = efipci_dma_ufree,
+ .umalloc = efipci_dma_alloc,
+ .ufree = efipci_dma_free,
.set_mask = efipci_dma_set_mask,
};
#include <string.h>
#include <errno.h>
#include <assert.h>
+#include <ipxe/uaccess.h>
#include <ipxe/umalloc.h>
#include <ipxe/efi/efi.h>
*
*/
-/** Equivalent of NOWHERE for user pointers */
-#define UNOWHERE ( ( userptr_t ) ~( ( intptr_t ) 0 ) )
-
/**
* Reallocate external memory
*
- * @v old_ptr Memory previously allocated by umalloc(), or UNULL
+ * @v old_ptr Memory previously allocated by umalloc(), or NULL
* @v new_size Requested size
- * @ret new_ptr Allocated memory, or UNULL
+ * @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 userptr_t efi_urealloc ( userptr_t old_ptr, size_t new_size ) {
+static void * efi_urealloc ( void *old_ptr, size_t new_size ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_PHYSICAL_ADDRESS phys_addr;
unsigned int new_pages, old_pages;
- userptr_t new_ptr = UNOWHERE;
+ void *new_ptr = NOWHERE;
size_t old_size;
+ size_t *info;
EFI_STATUS efirc;
int rc;
rc = -EEFI ( efirc );
DBG ( "EFI could not allocate %d pages: %s\n",
new_pages, strerror ( rc ) );
- return UNULL;
+ return NULL;
}
assert ( phys_addr != 0 );
new_ptr = phys_to_virt ( phys_addr + EFI_PAGE_SIZE );
- copy_to_user ( new_ptr, -EFI_PAGE_SIZE,
- &new_size, sizeof ( new_size ) );
+ info = ( new_ptr - EFI_PAGE_SIZE );
+ *info = new_size;
DBG ( "EFI allocated %d pages at %llx\n",
new_pages, phys_addr );
}
* is valid, or (b) new_size is 0; either way, the memcpy() is
* valid.
*/
- if ( old_ptr && ( old_ptr != UNOWHERE ) ) {
- copy_from_user ( &old_size, old_ptr, -EFI_PAGE_SIZE,
- sizeof ( old_size ) );
+ if ( old_ptr && ( old_ptr != NOWHERE ) ) {
+ info = ( old_ptr - EFI_PAGE_SIZE );
+ old_size = *info;
memcpy ( new_ptr, old_ptr,
( (old_size < new_size) ? old_size : new_size ) );
old_pages = ( EFI_SIZE_TO_PAGES ( old_size ) + 1 );
#include <ipxe/linux_api.h>
-/** Special address returned for empty allocations */
-#define NOWHERE ((void *)-1)
-
/** Poison to make the metadata more unique */
#define POISON 0xa5a5a5a5
#define min(a,b) (((a)<(b))?(a):(b))
#define SIZE_MD (sizeof(struct metadata))
-/** Simple realloc which passes most of the work to mmap(), mremap() and munmap() */
+/**
+ * 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 * linux_realloc(void *ptr, size_t size)
{
struct metadata md = {0, 0};
return ptr;
}
-/**
- * Reallocate external memory
- *
- * @v old_ptr Memory previously allocated by umalloc(), or UNULL
- * @v new_size Requested size
- * @ret new_ptr Allocated memory, or UNULL
- *
- * Calling realloc() with a new size of zero is a valid way to free a
- * memory block.
- */
-static userptr_t linux_urealloc(userptr_t old_ptr, size_t new_size)
-{
- return (userptr_t)linux_realloc((void *)old_ptr, new_size);
-}
-
-PROVIDE_UMALLOC(linux, urealloc, linux_urealloc);
+PROVIDE_UMALLOC(linux, urealloc, linux_realloc);
#include <stdio.h>
-#include <ipxe/uaccess.h>
#include <ipxe/umalloc.h>
#include <ipxe/io.h>
void umalloc_test ( void ) {
struct memory_map memmap;
- userptr_t bob;
- userptr_t fred;
+ void *bob;
+ void *fred;
printf ( "Before allocation:\n" );
get_memmap ( &memmap );