Browse Source

[umalloc] Split largest_memblock() function out from init_eheap()

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
fd141fb669
3 changed files with 106 additions and 49 deletions
  1. 8
    49
      src/arch/i386/interface/pcbios/memtop_umalloc.c
  2. 81
    0
      src/core/memblock.c
  3. 17
    0
      src/include/ipxe/memblock.h

+ 8
- 49
src/arch/i386/interface/pcbios/memtop_umalloc.c View File

@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
31 31
 #include <ipxe/uaccess.h>
32 32
 #include <ipxe/hidemem.h>
33 33
 #include <ipxe/io.h>
34
+#include <ipxe/memblock.h>
34 35
 #include <ipxe/umalloc.h>
35 36
 
36 37
 /** Alignment of external allocated memory */
@@ -59,53 +60,14 @@ static size_t heap_size;
59 60
 /**
60 61
  * Initialise external heap
61 62
  *
62
- * @ret rc		Return status code
63 63
  */
64
-static int init_eheap ( void ) {
65
-	struct memory_map memmap;
66
-	unsigned int i;
67
-
68
-	DBG ( "Allocating external heap\n" );
69
-
70
-	get_memmap ( &memmap );
71
-	heap_size = 0;
72
-	for ( i = 0 ; i < memmap.count ; i++ ) {
73
-		struct memory_region *region = &memmap.regions[i];
74
-		unsigned long r_start, r_end;
75
-		unsigned long r_size;
76
-
77
-		DBG ( "Considering [%llx,%llx)\n", region->start, region->end);
78
-
79
-		/* Truncate block to 4GB */
80
-		if ( region->start > UINT_MAX ) {
81
-			DBG ( "...starts after 4GB\n" );
82
-			continue;
83
-		}
84
-		r_start = region->start;
85
-		if ( region->end > UINT_MAX ) {
86
-			DBG ( "...end truncated to 4GB\n" );
87
-			r_end = 0; /* =4GB, given the wraparound */
88
-		} else {
89
-			r_end = region->end;
90
-		}
91
-
92
-		/* Use largest block */
93
-		r_size = ( r_end - r_start );
94
-		if ( r_size > heap_size ) {
95
-			DBG ( "...new best block found\n" );
96
-			top = bottom = phys_to_user ( r_end );
97
-			heap_size = r_size;
98
-		}
99
-	}
100
-
101
-	if ( ! heap_size ) {
102
-		DBG ( "No external heap available\n" );
103
-		return -ENOMEM;
104
-	}
64
+static void init_eheap ( void ) {
65
+	userptr_t base;
105 66
 
67
+	heap_size = largest_memblock ( &base );
68
+	bottom = top = userptr_add ( base, heap_size );
106 69
 	DBG ( "External heap grows downwards from %lx (size %zx)\n",
107 70
 	      user_to_phys ( top, 0 ), heap_size );
108
-	return 0;
109 71
 }
110 72
 
111 73
 /**
@@ -144,13 +106,10 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
144 106
 	struct external_memory extmem;
145 107
 	userptr_t new = ptr;
146 108
 	size_t align;
147
-	int rc;
148 109
 
149
-	/* Initialise external memory allocator if necessary */
150
-	if ( bottom == top ) {
151
-		if ( ( rc = init_eheap() ) != 0 )
152
-			return UNULL;
153
-	}
110
+	/* (Re)initialise external memory allocator if necessary */
111
+	if ( bottom == top )
112
+		init_eheap();
154 113
 
155 114
 	/* Get block properties into extmem */
156 115
 	if ( ptr && ( ptr != UNOWHERE ) ) {

+ 81
- 0
src/core/memblock.c View File

@@ -0,0 +1,81 @@
1
+/*
2
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ */
19
+
20
+FILE_LICENCE ( GPL2_OR_LATER );
21
+
22
+/** @file
23
+ *
24
+ * Largest memory block
25
+ *
26
+ */
27
+
28
+#include <stdint.h>
29
+#include <ipxe/uaccess.h>
30
+#include <ipxe/io.h>
31
+#include <ipxe/memblock.h>
32
+
33
+/**
34
+ * Find largest usable memory region
35
+ *
36
+ * @ret start		Start of region
37
+ * @ret len		Length of region
38
+ */
39
+size_t largest_memblock ( userptr_t *start ) {
40
+	struct memory_map memmap;
41
+	struct memory_region *region;
42
+	physaddr_t max = ~( ( physaddr_t ) 0 );
43
+	physaddr_t region_start;
44
+	physaddr_t region_end;
45
+	size_t region_len;
46
+	unsigned int i;
47
+	size_t len = 0;
48
+
49
+	/* Avoid returning uninitialised data on error */
50
+	*start = UNULL;
51
+
52
+	/* Scan through all memory regions */
53
+	get_memmap ( &memmap );
54
+	for ( i = 0 ; i < memmap.count ; i++ ) {
55
+		region = &memmap.regions[i];
56
+		DBG ( "Considering [%llx,%llx)\n", region->start, region->end );
57
+
58
+		/* Truncate block to maximum physical address */
59
+		if ( region->start > max ) {
60
+			DBG ( "...starts after maximum address %lx\n", max );
61
+			continue;
62
+		}
63
+		region_start = region->start;
64
+		if ( region->end > max ) {
65
+			DBG ( "...end truncated to maximum address %lx\n", max);
66
+			region_end = 0; /* =max, given the wraparound */
67
+		} else {
68
+			region_end = region->end;
69
+		}
70
+		region_len = ( region_end - region_start );
71
+
72
+		/* Use largest block */
73
+		if ( region_len > len ) {
74
+			DBG ( "...new best block found\n" );
75
+			*start = phys_to_user ( region_start );
76
+			len = region_len;
77
+		}
78
+	}
79
+
80
+	return len;
81
+}

+ 17
- 0
src/include/ipxe/memblock.h View File

@@ -0,0 +1,17 @@
1
+#ifndef _IPXE_MEMBLOCK_H
2
+#define _IPXE_MEMBLOCK_H
3
+
4
+/** @file
5
+ *
6
+ * Largest memory block
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#include <stdint.h>
13
+#include <ipxe/uaccess.h>
14
+
15
+extern size_t largest_memblock ( userptr_t *start );
16
+
17
+#endif /* _IPXE_MEMBLOCK_H */

Loading…
Cancel
Save