~ubuntu-branches/ubuntu/raring/ipxe/raring

« back to all changes in this revision

Viewing changes to src/arch/i386/interface/pcbios/memtop_umalloc.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-11-14 15:47:31 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20121114154731-jhuy5d1h2jw75qe9
Tags: 1.0.0+git-4.d6b0b76-0ubuntu1
* New upstream snapshot:
  - d/p/iscsi*.patch: Dropped - included in snapshot.
  - Refreshed all other patches.
* d/p/enable-https.patch: Enable HTTPS support (LP: #1025239).

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
 *
14
14
 * You should have received a copy of the GNU General Public License
15
15
 * along with this program; if not, write to the Free Software
16
 
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
17
 * 02110-1301, USA.
17
18
 */
18
19
 
19
20
FILE_LICENCE ( GPL2_OR_LATER );
30
31
#include <ipxe/uaccess.h>
31
32
#include <ipxe/hidemem.h>
32
33
#include <ipxe/io.h>
 
34
#include <ipxe/memblock.h>
33
35
#include <ipxe/umalloc.h>
34
36
 
35
37
/** Alignment of external allocated memory */
52
54
/** Bottom of heap (current lowest allocated block) */
53
55
static userptr_t bottom = UNULL;
54
56
 
 
57
/** Remaining space on heap */
 
58
static size_t heap_size;
 
59
 
55
60
/**
56
61
 * Initialise external heap
57
62
 *
58
 
 * @ret rc              Return status code
59
63
 */
60
 
static int init_eheap ( void ) {
61
 
        struct memory_map memmap;
62
 
        unsigned long heap_size = 0;
63
 
        unsigned int i;
64
 
 
65
 
        DBG ( "Allocating external heap\n" );
66
 
 
67
 
        get_memmap ( &memmap );
68
 
        for ( i = 0 ; i < memmap.count ; i++ ) {
69
 
                struct memory_region *region = &memmap.regions[i];
70
 
                unsigned long r_start, r_end;
71
 
                unsigned long r_size;
72
 
 
73
 
                DBG ( "Considering [%llx,%llx)\n", region->start, region->end);
74
 
 
75
 
                /* Truncate block to 4GB */
76
 
                if ( region->start > UINT_MAX ) {
77
 
                        DBG ( "...starts after 4GB\n" );
78
 
                        continue;
79
 
                }
80
 
                r_start = region->start;
81
 
                if ( region->end > UINT_MAX ) {
82
 
                        DBG ( "...end truncated to 4GB\n" );
83
 
                        r_end = 0; /* =4GB, given the wraparound */
84
 
                } else {
85
 
                        r_end = region->end;
86
 
                }
87
 
 
88
 
                /* Use largest block */
89
 
                r_size = ( r_end - r_start );
90
 
                if ( r_size > heap_size ) {
91
 
                        DBG ( "...new best block found\n" );
92
 
                        top = bottom = phys_to_user ( r_end );
93
 
                        heap_size = r_size;
94
 
                }
95
 
        }
96
 
 
97
 
        if ( ! heap_size ) {
98
 
                DBG ( "No external heap available\n" );
99
 
                return -ENOMEM;
100
 
        }
101
 
 
102
 
        DBG ( "External heap grows downwards from %lx\n",
103
 
              user_to_phys ( top, 0 ) );
104
 
        return 0;
 
64
static void init_eheap ( void ) {
 
65
        userptr_t base;
 
66
 
 
67
        heap_size = largest_memblock ( &base );
 
68
        bottom = top = userptr_add ( base, heap_size );
 
69
        DBG ( "External heap grows downwards from %lx (size %zx)\n",
 
70
              user_to_phys ( top, 0 ), heap_size );
105
71
}
106
72
 
107
73
/**
110
76
 */
111
77
static void ecollect_free ( void ) {
112
78
        struct external_memory extmem;
 
79
        size_t len;
113
80
 
114
81
        /* Walk the free list and collect empty blocks */
115
82
        while ( bottom != top ) {
119
86
                        break;
120
87
                DBG ( "EXTMEM freeing [%lx,%lx)\n", user_to_phys ( bottom, 0 ),
121
88
                      user_to_phys ( bottom, extmem.size ) );
122
 
                bottom = userptr_add ( bottom,
123
 
                                       ( extmem.size + sizeof ( extmem ) ) );
 
89
                len = ( extmem.size + sizeof ( extmem ) );
 
90
                bottom = userptr_add ( bottom, len );
 
91
                heap_size += len;
124
92
        }
125
93
}
126
94
 
138
106
        struct external_memory extmem;
139
107
        userptr_t new = ptr;
140
108
        size_t align;
141
 
        int rc;
142
109
 
143
 
        /* Initialise external memory allocator if necessary */
144
 
        if ( bottom == top ) {
145
 
                if ( ( rc = init_eheap() ) != 0 )
146
 
                        return UNULL;
147
 
        }
 
110
        /* (Re)initialise external memory allocator if necessary */
 
111
        if ( bottom == top )
 
112
                init_eheap();
148
113
 
149
114
        /* Get block properties into extmem */
150
115
        if ( ptr && ( ptr != UNOWHERE ) ) {
153
118
                                 sizeof ( extmem ) );
154
119
        } else {
155
120
                /* Create a zero-length block */
 
121
                if ( heap_size < sizeof ( extmem ) ) {
 
122
                        DBG ( "EXTMEM out of space\n" );
 
123
                        return UNULL;
 
124
                }
156
125
                ptr = bottom = userptr_add ( bottom, -sizeof ( extmem ) );
 
126
                heap_size -= sizeof ( extmem );
157
127
                DBG ( "EXTMEM allocating [%lx,%lx)\n",
158
128
                      user_to_phys ( ptr, 0 ), user_to_phys ( ptr, 0 ) );
159
129
                extmem.size = 0;
163
133
        /* Expand/shrink block if possible */
164
134
        if ( ptr == bottom ) {
165
135
                /* Update block */
 
136
                if ( new_size > ( heap_size - extmem.size ) ) {
 
137
                        DBG ( "EXTMEM out of space\n" );
 
138
                        return UNULL;
 
139
                }
166
140
                new = userptr_add ( ptr, - ( new_size - extmem.size ) );
167
141
                align = ( user_to_phys ( new, 0 ) & ( EM_ALIGN - 1 ) );
168
142
                new_size += align;
174
148
                      user_to_phys ( new, new_size ));
175
149
                memmove_user ( new, 0, ptr, 0, ( ( extmem.size < new_size ) ?
176
150
                                                 extmem.size : new_size ) );
 
151
                bottom = new;
 
152
                heap_size -= ( new_size - extmem.size );
177
153
                extmem.size = new_size;
178
 
                bottom = new;
179
154
        } else {
180
155
                /* Cannot expand; can only pretend to shrink */
181
156
                if ( new_size > extmem.size ) {
193
168
 
194
169
        /* Collect any free blocks and update hidden memory region */
195
170
        ecollect_free();
196
 
        hide_umalloc ( user_to_phys ( bottom, -sizeof ( extmem ) ),
 
171
        hide_umalloc ( user_to_phys ( bottom, ( ( bottom == top ) ?
 
172
                                                0 : -sizeof ( extmem ) ) ),
197
173
                       user_to_phys ( top, 0 ) );
198
174
 
199
175
        return ( new_size ? new : UNOWHERE );