Browse Source

[malloc] Allow allocation of memory with a specified alignment offset

Allow for allocation of memory blocks having a specified offset from a
specified physical alignment, such as being 12 bytes before a 2kB
boundary.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 11 years ago
parent
commit
e2becce186
2 changed files with 29 additions and 8 deletions
  1. 7
    5
      src/core/malloc.c
  2. 22
    3
      src/include/ipxe/malloc.h

+ 7
- 5
src/core/malloc.c View File

220
  *
220
  *
221
  * @v size		Requested size
221
  * @v size		Requested size
222
  * @v align		Physical alignment
222
  * @v align		Physical alignment
223
+ * @v offset		Offset from physical alignment
223
  * @ret ptr		Memory block, or NULL
224
  * @ret ptr		Memory block, or NULL
224
  *
225
  *
225
  * Allocates a memory block @b physically aligned as requested.  No
226
  * Allocates a memory block @b physically aligned as requested.  No
227
  *
228
  *
228
  * @c align must be a power of two.  @c size may not be zero.
229
  * @c align must be a power of two.  @c size may not be zero.
229
  */
230
  */
230
-void * alloc_memblock ( size_t size, size_t align ) {
231
+void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
231
 	struct memory_block *block;
232
 	struct memory_block *block;
232
 	size_t align_mask;
233
 	size_t align_mask;
233
 	size_t pre_size;
234
 	size_t pre_size;
244
 	size = ( size + MIN_MEMBLOCK_SIZE - 1 ) & ~( MIN_MEMBLOCK_SIZE - 1 );
245
 	size = ( size + MIN_MEMBLOCK_SIZE - 1 ) & ~( MIN_MEMBLOCK_SIZE - 1 );
245
 	align_mask = ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 );
246
 	align_mask = ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 );
246
 
247
 
247
-	DBG ( "Allocating %#zx (aligned %#zx)\n", size, align );
248
+	DBG ( "Allocating %#zx (aligned %#zx+%zx)\n", size, align, offset );
248
 	while ( 1 ) {
249
 	while ( 1 ) {
249
 		/* Search through blocks for the first one with enough space */
250
 		/* Search through blocks for the first one with enough space */
250
 		list_for_each_entry ( block, &free_blocks, list ) {
251
 		list_for_each_entry ( block, &free_blocks, list ) {
251
-			pre_size = ( - virt_to_phys ( block ) ) & align_mask;
252
-			post_size = block->size - pre_size - size;
252
+			pre_size = ( ( offset - virt_to_phys ( block ) )
253
+				     & align_mask );
254
+			post_size = ( block->size - pre_size - size );
253
 			if ( post_size >= 0 ) {
255
 			if ( post_size >= 0 ) {
254
 				/* Split block into pre-block, block, and
256
 				/* Split block into pre-block, block, and
255
 				 * post-block.  After this split, the "pre"
257
 				 * post-block.  After this split, the "pre"
418
 	if ( new_size ) {
420
 	if ( new_size ) {
419
 		new_total_size = ( new_size +
421
 		new_total_size = ( new_size +
420
 				   offsetof ( struct autosized_block, data ) );
422
 				   offsetof ( struct autosized_block, data ) );
421
-		new_block = alloc_memblock ( new_total_size, 1 );
423
+		new_block = alloc_memblock ( new_total_size, 1, 0 );
422
 		if ( ! new_block )
424
 		if ( ! new_block )
423
 			return NULL;
425
 			return NULL;
424
 		VALGRIND_MAKE_MEM_UNDEFINED ( new_block, offsetof ( struct autosized_block, data ) );
426
 		VALGRIND_MAKE_MEM_UNDEFINED ( new_block, offsetof ( struct autosized_block, data ) );

+ 22
- 3
src/include/ipxe/malloc.h View File

23
 
23
 
24
 extern size_t freemem;
24
 extern size_t freemem;
25
 
25
 
26
-extern void * __malloc alloc_memblock ( size_t size, size_t align );
26
+extern void * __malloc alloc_memblock ( size_t size, size_t align,
27
+					size_t offset );
27
 extern void free_memblock ( void *ptr, size_t size );
28
 extern void free_memblock ( void *ptr, size_t size );
28
 extern void mpopulate ( void *start, size_t len );
29
 extern void mpopulate ( void *start, size_t len );
29
 extern void mdumpfree ( void );
30
 extern void mdumpfree ( void );
33
  *
34
  *
34
  * @v size		Requested size
35
  * @v size		Requested size
35
  * @v align		Physical alignment
36
  * @v align		Physical alignment
37
+ * @v offset		Offset from physical alignment
36
  * @ret ptr		Memory, or NULL
38
  * @ret ptr		Memory, or NULL
37
  *
39
  *
38
  * Allocates physically-aligned memory for DMA.
40
  * Allocates physically-aligned memory for DMA.
39
  *
41
  *
40
  * @c align must be a power of two.  @c size may not be zero.
42
  * @c align must be a power of two.  @c size may not be zero.
41
  */
43
  */
42
-static inline void * __malloc malloc_dma ( size_t size, size_t phys_align ) {
43
-	void * ptr = alloc_memblock ( size, phys_align );
44
+static inline void * __malloc malloc_dma_offset ( size_t size,
45
+						  size_t phys_align,
46
+						  size_t offset ) {
47
+	void * ptr = alloc_memblock ( size, phys_align, offset );
44
 	if ( ptr && size )
48
 	if ( ptr && size )
45
 		VALGRIND_MALLOCLIKE_BLOCK ( ptr, size, 0, 0 );
49
 		VALGRIND_MALLOCLIKE_BLOCK ( ptr, size, 0, 0 );
46
 	return ptr;
50
 	return ptr;
47
 }
51
 }
48
 
52
 
53
+/**
54
+ * Allocate memory for DMA
55
+ *
56
+ * @v size		Requested size
57
+ * @v align		Physical alignment
58
+ * @ret ptr		Memory, or NULL
59
+ *
60
+ * Allocates physically-aligned memory for DMA.
61
+ *
62
+ * @c align must be a power of two.  @c size may not be zero.
63
+ */
64
+static inline void * __malloc malloc_dma ( size_t size, size_t phys_align ) {
65
+	return malloc_dma_offset ( size, phys_align, 0 );
66
+}
67
+
49
 /**
68
 /**
50
  * Free memory allocated with malloc_dma()
69
  * Free memory allocated with malloc_dma()
51
  *
70
  *

Loading…
Cancel
Save