From d948e2b1f98ddf2449dcf59dbc46d64f3ea0d311 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Mon, 12 Oct 2009 12:54:56 -0400 Subject: [PATCH] Use pmm_malloc() for internal allocations. Using pmm_malloc permits free() to be used on internal allocations. Rework low zone expanding so that it doesn't cause gcc v4.3 error. Allow pmm_malloc to use ZoneTmpLow if ZoneTmpHigh isn't available. --- src/pmm.c | 115 ++++++++++++++++++++++++----------------------------- src/util.h | 22 +++++----- 2 files changed, 64 insertions(+), 73 deletions(-) diff --git a/src/pmm.c b/src/pmm.c index e90a7a8..9e1a9c5 100644 --- a/src/pmm.c +++ b/src/pmm.c @@ -66,33 +66,38 @@ relocate_ebda(u32 newebda, u32 oldebda, u8 ebda_size) } // Support expanding the ZoneLow dynamically. -static int +static void zonelow_expand(u32 size, u32 align) { + u32 oldpos = GET_PMMVAR(ZoneLow.cur); + u32 newpos = ALIGN_DOWN(oldpos - size, align); + u32 bottom = GET_PMMVAR(ZoneLow.bottom); + if (newpos >= bottom && newpos <= oldpos) + // Space already present. + return; u16 ebda_seg = get_ebda_seg(); u32 ebda_pos = (u32)MAKE_FLATPTR(ebda_seg, 0); - u32 bottom = GET_PMMVAR(ZoneLow.bottom); - u32 cur = GET_PMMVAR(ZoneLow.cur); u8 ebda_size = GET_EBDA2(ebda_seg, size); u32 ebda_end = ebda_pos + ebda_size * 1024; - if (ebda_end != bottom) + if (ebda_end != bottom) { // Something else is after ebda - can't use any existing space. - cur = ebda_end; - u32 newcur = ALIGN_DOWN(cur - size, align); - u32 newbottom = ALIGN_DOWN(newcur, 1024); + oldpos = ebda_end; + newpos = ALIGN_DOWN(oldpos - size, align); + } + u32 newbottom = ALIGN_DOWN(newpos, 1024); u32 newebda = ALIGN_DOWN(newbottom - ebda_size * 1024, 1024); if (newebda < BUILD_EBDA_MINIMUM) // Not enough space. - return -1; + return; // Move ebda int ret = relocate_ebda(newebda, ebda_pos, ebda_size); if (ret) - return ret; + return; // Update zone + SET_PMMVAR(ZoneLow.cur, oldpos); SET_PMMVAR(ZoneLow.bottom, newbottom); - return 0; } @@ -101,7 +106,7 @@ zonelow_expand(u32 size, u32 align) ****************************************************************/ // Obtain memory from a given zone. -void * +static void * zone_malloc(struct zone_s *zone, u32 size, u32 align) { u32 oldpos = GET_PMMVAR(zone->cur); @@ -113,15 +118,6 @@ zone_malloc(struct zone_s *zone, u32 size, u32 align) return (void*)newpos; } -// Return memory to a zone (if it was the last to be allocated). -static void -zone_free(struct zone_s *zone, void *data, u32 olddata) -{ - if (! data || GET_PMMVAR(zone->cur) != (u32)data) - return; - SET_PMMVAR(zone->cur, olddata); -} - // Find the zone that contains the given data block. static struct zone_s * zone_find(void *data) @@ -136,6 +132,17 @@ zone_find(void *data) return NULL; } +// Return memory to a zone (if it was the last to be allocated). +static int +zone_free(void *data, u32 olddata) +{ + struct zone_s *zone = zone_find(data); + if (!zone || !data || GET_PMMVAR(zone->cur) != (u32)data) + return -1; + SET_PMMVAR(zone->cur, olddata); + return 0; +} + // Report the status of all the zones. static void dumpZones() @@ -209,17 +216,6 @@ malloc_finalize() memset((void*)ZoneTmpLow.bottom, 0, ZoneTmpLow.top - ZoneTmpLow.bottom); } -// Allocate memory from ZoneLow - growing the zone if needed. -void * -zone_malloc_low(u32 size, u32 align) -{ - void *ret = zone_malloc(&ZoneLow, size, align); - if (ret) - return ret; - zonelow_expand(size, align); - return zone_malloc(&ZoneLow, size, align); -} - /**************************************************************** * pmm allocation @@ -236,30 +232,25 @@ struct pmmalloc_s { struct pmmalloc_s *PMMAllocs VAR32VISIBLE; -// Memory zone that pmm allocation tracking info is stored in -#define ZONEALLOC (&ZoneTmpHigh) - // Allocate memory from the given zone and track it as a PMM allocation -static void * +void * pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align) { - u32 oldallocdata = GET_PMMVAR(ZONEALLOC->cur); - struct pmmalloc_s *info = zone_malloc(ZONEALLOC, sizeof(*info) + u32 oldallocdata = GET_PMMVAR(ZoneTmpHigh.cur); + struct pmmalloc_s *info = zone_malloc(&ZoneTmpHigh, sizeof(*info) , MALLOC_MIN_ALIGN); - if (!info) - return NULL; + if (!info) { + oldallocdata = GET_PMMVAR(ZoneTmpLow.cur); + info = zone_malloc(&ZoneTmpLow, sizeof(*info), MALLOC_MIN_ALIGN); + if (!info) + return NULL; + } + if (zone == &ZoneLow) + zonelow_expand(size, align); u32 olddata = GET_PMMVAR(zone->cur); void *data = zone_malloc(zone, size, align); -#if 0 // XXX - gcc4.3 internal compiler error - disable for now - if (!data && zone == &ZoneLow) { - // Try to expand permanent low zone. - zonelow_expand(size, align); - olddata = GET_PMMVAR(zone->cur); - data = zone_malloc(zone, size, align); - } -#endif if (! data) { - zone_free(ZONEALLOC, info, oldallocdata); + zone_free(info, oldallocdata); return NULL; } dprintf(8, "pmm_malloc zone=%p handle=%x size=%d align=%x" @@ -277,12 +268,12 @@ pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align) // Free a raw data block (either from a zone or from pmm alloc list). static void -pmm_free_data(struct zone_s *zone, void *data, u32 olddata) +pmm_free_data(void *data, u32 olddata) { - if (GET_PMMVAR(zone->cur) == (u32)data) { - zone_free(zone, data, olddata); + int ret = zone_free(data, olddata); + if (!ret) + // Success - done. return; - } struct pmmalloc_s *info; for (info=GET_PMMVAR(PMMAllocs); info; info = GET_PMMVAR(info->next)) if (GET_PMMVAR(info->olddata) == (u32)data) { @@ -295,12 +286,9 @@ pmm_free_data(struct zone_s *zone, void *data, u32 olddata) } // Free a data block allocated with pmm_malloc -static int +int pmm_free(void *data) { - struct zone_s *zone = zone_find(GET_PMMVAR(data)); - if (!zone) - return -1; struct pmmalloc_s **pinfo = &PMMAllocs; for (;;) { struct pmmalloc_s *info = GET_PMMVAR(*pinfo); @@ -310,12 +298,10 @@ pmm_free(void *data) SET_PMMVAR(*pinfo, GET_PMMVAR(info->next)); u32 oldallocdata = GET_PMMVAR(info->oldallocdata); u32 olddata = GET_PMMVAR(info->olddata); - pmm_free_data(zone, data, olddata); - pmm_free_data(ZONEALLOC, info, oldallocdata); - dprintf(8, "pmm_free data=%p zone=%p olddata=%p oldallocdata=%p" - " info=%p\n" - , data, zone, (void*)olddata, (void*)oldallocdata - , info); + pmm_free_data(data, olddata); + pmm_free_data(info, oldallocdata); + dprintf(8, "pmm_free data=%p olddata=%p oldallocdata=%p info=%p\n" + , data, (void*)olddata, (void*)oldallocdata, info); return 0; } pinfo = &info->next; @@ -328,8 +314,9 @@ pmm_getspace(struct zone_s *zone) { // XXX - doesn't account for ZoneLow being able to grow. u32 space = GET_PMMVAR(zone->cur) - GET_PMMVAR(zone->bottom); - if (zone != ZONEALLOC) + if (zone != &ZoneTmpHigh && zone != &ZoneTmpLow) return space; + // Account for space needed for PMM tracking. u32 reserve = ALIGN(sizeof(struct pmmalloc_s), MALLOC_MIN_ALIGN); if (space <= reserve) return 0; @@ -441,7 +428,7 @@ handle_pmm01(u16 *args) { u32 handle = *(u32*)&args[1]; dprintf(3, "pmm01: handle=%x\n", handle); - if (handle == 0xFFFFFFFF) + if (handle == PMM_DEFAULT_HANDLE) return 0; return (u32)pmm_find(handle); } diff --git a/src/util.h b/src/util.h index ca3aa31..c7fa261 100644 --- a/src/util.h +++ b/src/util.h @@ -282,35 +282,39 @@ void pnp_setup(); // pmm.c extern struct zone_s ZoneLow, ZoneHigh, ZoneFSeg, ZoneTmpLow, ZoneTmpHigh; -void *zone_malloc(struct zone_s *zone, u32 size, u32 align); -void *zone_malloc_low(u32 size, u32 align); void malloc_setup(); void malloc_finalize(); +void *pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align); +int pmm_free(void *data); void pmm_setup(); void pmm_finalize(); +#define PMM_DEFAULT_HANDLE 0xFFFFFFFF // Minimum alignment of malloc'd memory #define MALLOC_MIN_ALIGN 16 // Helper functions for memory allocation. static inline void *malloc_low(u32 size) { - return zone_malloc_low(size, MALLOC_MIN_ALIGN); + return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); } static inline void *malloc_high(u32 size) { - return zone_malloc(&ZoneHigh, size, MALLOC_MIN_ALIGN); + return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); } static inline void *malloc_fseg(u32 size) { - return zone_malloc(&ZoneFSeg, size, MALLOC_MIN_ALIGN); + return pmm_malloc(&ZoneFSeg, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); } static inline void *malloc_tmphigh(u32 size) { - return zone_malloc(&ZoneTmpHigh, size, MALLOC_MIN_ALIGN); + return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN); } static inline void *memalign_low(u32 align, u32 size) { - return zone_malloc_low(size, align); + return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, align); } static inline void *memalign_high(u32 align, u32 size) { - return zone_malloc(&ZoneHigh, size, align); + return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, align); } static inline void *memalign_tmphigh(u32 align, u32 size) { - return zone_malloc(&ZoneTmpHigh, size, align); + return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, align); +} +static inline void free(void *data) { + pmm_free(data); } // mtrr.c -- 2.25.1